2009-08-02 7 views
11

Kiedy opracowałem kawałek (akademickiego) oprogramowania wykorzystującego Javę, zmuszony byłem użyć API, który został źle wdrożony. Oznacza to, że wywołania tego interfejsu API dla określonego zestawu danych wejściowych czasami nigdy nie powrócą. Musiał to być błąd w oprogramowaniu, ponieważ oferowane przez niego algorytmy były deterministyczne, a czasami kończyłoby się na zbiorze danych, czasami działałby w nieskończoną pętlę na tym samym zbiorze danych ...Jak wyizolować program z połączeń na "zły" interfejs API?

Naprawianie lub ponowne wdrażanie interfejsu API było jednak poza zakresem. Miałem nawet źródło, ale API silnie polegało na innych API, które były nieudokumentowane i bez źródła, a do tego czasu zniknęły z sieci (lub nigdy tam nie były?). Z drugiej strony ten "zły" API był jedynym, który rozwiązał konkretny problem, który miałem, więc naprawdę musiałem się z tym uporać.

Pytanie brzmi: jaki jest najczystszy sposób radzenia sobie z interfejsem API, który zachowuje się tak, nieprzyjemnie? Kiedy stanąłem przed tym problemem, postanowiłem umieścić wywołania interfejsu API w osobnym wątku. Inny wątek czasami sprawdzałby, czy wątek został zakończony. Jeśli upłynął pewien czas, zabiłbym wątek przetwarzania za pomocą Thread#stop() i ponownie rozpoczynam przetwarzanie, mając nadzieję, że nastąpi ono następnym razem. Teraz wiem (i wiedziałem wtedy), że ta metoda jest przestarzała i nie wolno jej używać. Ale w tym kontekście akademickim było dopuszczalne, aby oprogramowanie mogło być niezdefiniowane, zamiast powodować awarię.

Niedopuszczalne było także ignorowanie wątku przetwarzania, który został uruchomiony w nieskończonej pętli, ponieważ wykonał on dość intensywne operacje, które znacznie spowolniłyby pracę maszyny użytkownika.

Innym sposobem, którego nie próbowałem, jest rozpoczęcie przetwarzania w oddzielnym procesie zamiast wątku, ponieważ pod-proces może zostać całkowicie zniszczony bez wprowadzania oprogramowania w niespójny stan. A może nowa klasa SwingWorker (która nie była jeszcze dostępna) wykonała zadanie? Ma on metodę cancel(), ale dokumentacja mówi, że jest to "Próba anulowania wykonania tego zadania", więc nie wygląda na niezawodne podejście.

Odpowiedz

11

Polecam stosowanie oddzielnego procesu. Zasadniczo nie ma bezpiecznego sposobu, aby jeden wątek zabił drugi wątek w Javie, chyba że drugi wątek okresowo sprawdza, czy został przerwany.

Idealnym rozwiązaniem byłoby użycie izolatów. Izolat to w zasadzie prywatna maszyna wirtualna, którą aplikacja Java może tworzyć, zarządzać i komunikować się z nią. W szczególności aplikacja nadrzędna może bezpiecznie zabić izolat i wszystkie jego wątki.

referencyjny: JSR-000121 Application Isolation API Specification - Final Release

Problemem jest znalezienie JVM, który obsługuje izolatów.

+1

Zaakceptowałem twoją odpowiedź z powodu interesującego odniesienia do Isolation API. Dziękuję za to! –

5

Jestem wielkim fanem oddzielnych procesów dla tego typu rzeczy.

Pomiń podproces i czekaj na wyniki.

Jeśli interfejs API nie jest deterministyczny, należy umieścić wątek z timerem w opakowaniu, które powoduje, że zły interfejs API staje się programem głównym.

W ten sposób podproces zawsze kończy się w określonym czasie. Jest to albo użyteczny wynik, albo kod wyjścia systemu, który wskazuje awarię.

+0

Dzięki za odpowiedź, myślę, że spróbuję tego podejścia. –

1

Jednym z zadań, jakie należy wykonać, to ponowne wdrożenie danego interfejsu API. Jednak, jak mówisz, jest to bardzo ciężkie i prawdopodobnie poza zakresem rozwiązanie.

Najlepiej byłoby, gdyby owinął API, jeśli to możliwe. Zasadniczo, jeśli możesz określić z góry, co to jest o zestawach danych, które powodują awarię, możesz odrzucić odrzucić wywołania w celu zagwarantowania determinizmu. Nie wygląda na to, że to zadziała również dla ciebie, ponieważ sugerujesz, że powtarzanie połączenia z tym samym zestawem danych czasami kończy się, gdy w nieskończenie zapętlonym wywołaniu.

Biorąc pod uwagę powyższe opcje powyżej nie są dostępne:
Myślę, że obecne rozwiązanie gwint jest najlepiej złych wyborów. Przędzenie procesu wywołania metody wydaje się zbyt dużą wagą, aby można ją było zaakceptować z punktu widzenia wydajności, nawet jeśli jest bezpieczniejsze niż używanie wątków. Thread.stop() jest bardzo niebezpieczny, ale jeśli religijnie zapobiegniesz blokowaniu, możesz sobie z tym poradzić.

+0

Nie całkiem się z tobą zgadzam. W danym momencie może być tylko jeden pod-proces. Wewnątrz tego pod-procesu miałyby miejsce naprawdę intensywne obliczenia procesora, więc nie widzę powodu, dla którego tworzenie kolejnego procesu jest tak wielką sprawą. Przypuszczam, że zakładasz, że byłoby wiele podprocesów, ale mój program zawsze potrzebowałby tylko jednego. Byłby jednak pewien napływ do pobierania i pobierania danych do iz niego, ale nie byłoby to zbyt trudne. Cóż, dziękuję za odpowiedź. –

+0

Moja troska dotyczy kosztu __starting__ procesu, a nie liczby lub procesów na żywo w danym momencie. Koszt procesu >> koszt wątku pod względem czasu uruchamiania. Zakładam, że wielokrotnie robisz połączenia z tym interfejsem API, co moim zdaniem jest sprawiedliwe, biorąc pod uwagę to, co zostało napisane (choć może nie jest to prawdą w twojej obecnej sytuacji). Sposób, w jaki procesor jest intensywny, nie jest tak naprawdę istotny, ponieważ płacisz ten koszt niezależnie od poprawki. –

2

Zarówno odpowiedzi @ S.Lott, jak i @Stephen C są przydatne w odniesieniu do sposobu radzenia sobie z takimi sytuacjami, ale chciałbym dodać, że w środowisku innym niż akademickim należy również dążyć do zastąpienia API tak szybko, jak to możliwe. W sytuacjach, gdy byliśmy zablokowani w złym API, zazwyczaj poprzez wybór rozwiązania z innymi przyczynami, pracowałem nad zastąpieniem tej funkcji moim własnym czasem. Twoi klienci nie będą tak tolerancyjni jak twoi profesorowie, ponieważ będą musieli używać twojego oprogramowania (lub nie!) Zamiast jedynie oceniać to.

Z pewnością istnieją sytuacje, w których używanie taśmy klejącej jest odpowiednim wyborem, aby rozwiązać problem. Kiedy powoduje to tak słabe zachowanie, jak opisujesz, najlepiej nie polegać na nim zbyt długo i zacząć pracować nad prawdziwą naprawą.

+0

Cóż, widziałem (raczej drogie) oprogramowanie biznesowe, które często padało i było akceptowane przez wszystkich, ponieważ było to jedyne dostępne oprogramowanie do określonego celu. Obejście też istniało, tak samo jak w przypadku mojej aplikacji: zabij proces i spróbuj ponownie ;-) Myślę, że Joel mówił o takim oprogramowaniu w podcastie SO, ale nie mogę znaleźć tego odcinka już teraz. Mam tu na myśli naprawdę paskudne oprogramowanie, niewiarygodne i z okropnym interfejsem, ale nadal jest niezwykle skuteczne, ponieważ jest jedynym rozwiązaniem naprawdę skomplikowanego problemu. –

+2

Gdy naprawdę kiepskie oprogramowanie jest najlepsze dostępne, a ludzie są gotowi za to zapłacić, nazywa się to szansą. – tvanfosson

Powiązane problemy