2009-06-21 14 views
30

Używam java.util.concurrent.Semaphore w projekcie hobby. Jest używany w klasie puli połączeń, którą piszę. Można go używać z małego zamieszania, z wyjątkiem tej metody:Czy muszę się martwić o Przerwany Wyjątek, jeśli sam niczego nie przerywam?

public void acquire(int permits) throws InterruptedException 

który zmusza mnie do obsługi InterruptedException. Teraz nie jestem pewien, co oznacza "przerywanie" Nici, a ja nigdy tego nie robię (no, właściwie nie tak) w moim kodzie. Czy to oznacza, że ​​mogę zignorować wyjątek? Jak mam sobie z tym poradzić?

Odpowiedz

1

Wątki można przerwać, wywołując Thread.interrupt(). Służy do wdzięcznego sygnalizowania wątku, że powinien zrobić coś innego. Zwykle powoduje to, że operacje blokujące (na przykład Thread.sleep()) wracają wcześniej i wywołują wyjątek InterruptedException. Jeśli wątek zostanie przerwany, zostanie ustawiona flaga. Tę flagę można sprawdzić za pomocą wywołania Thread.isInterrupted().

Jeśli nie używasz przerwania wątków i nadal otrzymujesz ten wyjątek, możesz po prostu opuścić wątek (i najlepiej zarejestrować wyjątek).

Zasadniczo zależy to od aplikacji wielowątkowej.

0

Należy zamknąć metodę run() po wykonaniu czyszczenia wymaganego przez wątek.
HTH

6

Nie. InterruptedException jest generowany tylko wtedy, gdy sam przerwiesz wątek. Jeśli nie używasz Thread.interrupt(), to albo powinienem je ponownie rzucić jako "nieoczekiwany wyjątek" albo zalogować jako błąd i przejść dalej. Na przykład w moim kodzie, gdy jestem zmuszony do połowu InterruptedException i nigdy zadzwonić interrupt() siebie, robię równowartość

catch (InterruptedException exception) { 
    throw new RuntimeException("Unexpected interrupt", exception); 
} 

to jeśli jest to nieoczekiwane. Jest wiele miejsc, w których celowo przerywa mi wątki iw tych przypadkach obsługuję je w ściśle określony sposób. Zwykle jest to wyjście z pętli, w której się znajduję, czyszczenie, a następnie zatrzymywanie wątku.

1

Jeśli nie wiesz jak obsługiwać go w metodzie Proponuję zgłosić go w metodzie z rzutów InterruptedException (a rozmówca etc)

Jeśli to coś nigdy nie można oczekiwać, aby wystąpić bym go złapać i zawiń go w AssertionError.

27

Tak, musisz martwić się o InterruptedException, tak jak musisz martwić się o każdy inny sprawdzony wyjątek, który musisz albo rzucić lub obsługiwać.

W większości przypadków InterruptedException sygnalizuje żądanie zatrzymania, najprawdopodobniej ze względu na fakt, że wątek, na którym działał twój kod, to interrupted.

W konkretnej sytuacji w puli połączeń oczekujących na wykupienie połączenia, powiedziałbym, że jest to problem z anulowaniem i należy przerwać odbieranie, czyszczenie i przywracanie przerwanej flagi (patrz poniżej).


Jako przykład, jeśli używasz jakiegoś Runnable/Callable działa wewnątrz Executor to trzeba obsłużyć InterruptedException odpowiednio:

executor.execute(new Runnable() { 

    public void run() { 
     while (true) { 
       try { 
       Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        continue; //blah 
       } 
       pingRemoteServer(); 
     } 
    } 
}); 

Oznaczałoby to, że zadanie nie przestrzega mechanizm przerwania używany przez wykonawcę i nie pozwala na właściwe anulowanie/zamknięcie.

Zamiast właściwego idiomu jest przywrócenie stanu przerwany, a następnie zatrzymać wykonanie:

executor.execute(new Runnable() { 

    public void run() { 
     while (true) { 
       try { 
       Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        Thread.currentThread().interrupt(); // restore interrupted status 
        break; 
       } 
       pingRemoteServer(); 
     } 
    } 
}); 

Przydatne zasoby:

+3

Absolutnie. Aby uzyskać więcej informacji, zobacz biuletyn Java Specialists http://www.javaspecialists.co.za/archive/Issue056.html –

+1

Nie powinien to być Thread.currentThread(). Interrupt() zamiast Thread.interrupted()? Według javadocs, Thread.interrupted() wyczyści przerwaną flagę, a nie ustawi ją. –

+0

@Joe: masz rację, poprawiłem przykład. Dziękuję Ci. –

Powiązane problemy