2012-10-10 11 views
13

jaka jest najlepsza praktyka w obsłudze InterruptedException s przy użyciu Throwables.propagate (e) w Guava?Guava: Throwables.propagate i InterruptedException

Uwielbiam używać throw Throwables.propagate(e), szczególnie w metodach, które nie zawierają sprawdzonych wyjątków i gdzie obsługa wyjątków jest obowiązkiem dzwoniącego. Ale nie robi to, czego oczekiwałbym dzięki InterruptedException.

Nie chcę stracić fakt, że wątek został przerwany, więc skończę pisać takie rzeczy jak:

public void run() { 
    Callable c = ...; 
    try { 
     c.call(); 
    } catch (InterruptedException e) { 
     Thread.currentThread().interrupt(); 
     throw Throwables.propagate(e); 
    } catch (Exception e) { 
     throw Throwables.propagate(e); 
    } 
} 

Czy istnieje sposób, aby zrobić to w Guava? Czy istnieje (kompatybilny wstecz ?!) sposób użycia czegoś takiego jak Throwables.propagate(), który ustawia wątek jako przerwany, jeśli jest to pakowanie i propagowanie wyjątku InterruptedException?

+1

Podnosiłbym to jako żądanie funkcji w Guava – artbristol

Odpowiedz

7

Dogodnie omawialiśmy to wewnętrznie jakiś czas temu. Ja po prostu skopiuj i wklej:

Moim zdaniem trudno linia Throwables.propagate(e) jest to, że w zasadzie throw new RuntimeException(e) i że ludzie zazwyczaj nie powinien to zrobić, tak jak zwykle nie powinno się pisać throw new RuntimeException(e). (A jeśli zamierzają to napisać, mogą napisać to wprost, żeby było jasne, co się dzieje.)

Moja twarda opinia na temat catch (Exception e) - zazwyczaj ludzie wpadają w ten bałagan - jest to, że zwykle też nie powinni tego robić. (Oczywiście są przypadki, w których catch (Exception e) jest oczywiście właściwą rzeczą do zrobienia (w zasadzie dowolny blok blokujący na najwyższym poziomie operacyjnym), ale są one ... oczywiste.)

Moja twarda opinia na temat InterruptedException jest to, że w sumie InterruptedException implementuje się w następujący sposób: wymaga specjalnego traktowania, z wyjątkiem innych wyjątków.

Moja twarda opinia na temat zamiany InterruptedException na RuntimeException to "nie". (To, jak wiele innych rzeczy, które powiedziałem powyżej, jest kontrowersyjne.)

Tak więc z jednej strony nie jestem pewien, czy możemy coś zrobić, aby uratować propagate(). Z drugiej strony, może miło jest uczynić tę metodę nieco mniej złą.

Następnie ponownie rozważyć tę rozmówcę, który łapie ExecutionException e:

throw Throwables.propagate(e.getCause());

Błędem byłoby przerwać nić konsumentów, podobnie jak błędem byłoby rzucić e.getCause() bezpośrednio, ponieważ przerwa była przeznaczona dla wątku komputerowego, a nie dla wątku konsumenta.

Jestem skłonny opuścić propagate() sam. (Jak można się domyślać, osobiście jestem skłonny to zrobić, ale to ważniejsza dyskusja.)

+1

+1 interesujące punkty. Jestem zdumiony, że ludzie piszą: "throw Throwables.propagate (e.getCause());'! Ślad stosu będzie wyglądał tak, jakby wszystko działo się w jednym wątku! – artbristol

+1

Dzięki, ciekawe punkty. +1 do InterruptedException implementującego wyjątek będący nieprawidłowy, ale Java jest tam, gdzie jest. Myślę, że konwersja wyjątku InterruptedException do wyjątku RuntimeException jest czasami niezbędna: jeśli mój podpis metody jest ustalony przez interfejs zewnętrzny (nie mogę więc rzucić wyjątku InterruptedException), a moja operacja została przerwana (tak, że nie mogę wypełnić mojej umowy), musi rzucić wyjątek. Jaka jest inna rozsądna opcja, poza ustawianiem wątku jako przerwanym i wyrzucaniem wyjątku RuntimeException? –

+4

Zamiast pisać 'throw new RuntimeException (e)', jest to denerwujące, że wyjątek jest zawijany w wyjątek (szczególnie, gdy nie dodaje nic użytecznego, na przykład dodatkowej wiadomości o bieżącym kontekście). Wszędzie tam, gdzie można uniknąć tego szumu (np. Jest to już niesprawdzony wyjątek), to świetnie. Istnieje szkoła myśli, że interfejsy API powinny używać niezaznaczonych wyjątków, gdy tylko jest to możliwe. Nawet jeśli ktoś nie kupi tej argumentacji, nadal musi implementować interfejsy innych ludzi napisane w ten sposób. Proszę więc nie usuwać 'Throwables.propagate (e)'! –