2015-03-12 12 views
7

Biorąc pod uwagę ten kod ...Nie można przerwać wątku, jeśli faktycznie jest to obliczanie?

public class SimpleTest { 

    @Test 
    public void testCompletableFuture() throws Exception { 
    Thread thread = new Thread(SimpleTest::longOperation); 
    thread.start(); 

    bearSleep(1); 

    thread.interrupt(); 

    bearSleep(5); 
    } 

    public static void longOperation(){ 
    System.out.println("started"); 
    try { 

     boolean b = true; 
     while (true) { 
     b = !b; 
     } 

    }catch (Exception e){ 
     System.out.println("exception happened hurray!"); 
    } 
    System.out.println("completed"); 
    } 

    private static void bearSleep(long seconds){ 
    try { 
     TimeUnit.SECONDS.sleep(seconds); 
    } catch (InterruptedException e) {} 
    } 
} 

Wyobraźmy sobie, że zamiast tego while(true) masz coś, co nie rzuca przerwany wykonanie (na przykład funkcji rekurencyjnej, że faktycznie coś oblicza).

Jak zabić tę rzecz? I dlaczego nie umiera?

Uwaga, jeśli nie wstawię tam typu Exception i nie użyję InterruptedException, to nawet nie skompiluję, mówiąc, że nie rozumiem, dlaczego to jest "interrupted exception will never be thrown". Może chcę ręcznie go przerwać ...

Odpowiedz

4

Zakładam, że odnosimy się do tego segmentu kodu:

try { 
    boolean b = true; 
    while (true) { 
     b = !b; 
    } 
} catch(Exception e) { 
    System.out.println("exception happened hurray!"); 
} 

Powodem nie można złapać InterruptedException tutaj jest, bo nie ma nic wewnątrz tego bloku, który może rzucić InterruptedException. interrupt() sama nie przerwie wątku z pętli, zamiast tego zasadniczo wysyła sygnał do wątku, aby powiedzieć mu, aby zatrzymać to, co robi i zrobić coś innego. Jeśli chcesz interrupt() przerwać pętlę, spróbuj tego:

boolean b = true; 
while (true) { 
    b = !b; 
    // Check if we got interrupted. 
    if(Thread.interrupted()) { 
     break; // Break out of the loop. 
    } 
} 

Teraz wątek będzie sprawdzić, czy został przerwany i wyrwać się z pętli po jej. Nie jest konieczne.

+1

Należy pamiętać, że za pomocą [Thread.interrupted()] (http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#interrupted%28%29) * Przerwany status wątek jest czyszczony tą metodą. * – OldCurmudgeon

+3

To prawda. Jeśli chcesz zachować status flagi "interrupted", metoda instancji [Thread.isInterrupted()] (http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html # is Interrupted% 28% 29) powinien być użyty zamiast tego. –

2

Thread#interrupt jest w mniejszym lub większym stopniu zaimplementowana z flagą. Jeśli wątek jest blokowany przy niektórych akcjach, np. IO lub prymitywach synchronizacji (zobacz Javadoc), wątek jest odblokowywany, a wątek jest zapisywany jako InterruptedException. W przeciwnym razie ustawiona jest prosta flaga statusu wskazująca, że ​​wątek został przerwany.

Twój kod musi sprawdzić ten stan za pomocą Thread#interrupted() lub Thread#isInterrupted() (lub obsłużyć InterruptedException).

Należy pamiętać, że sprawdzenie statusu za pomocą metody static powoduje usunięcie statusu.

+0

ok, więc w takim przypadku właściwą drogą jest sprawdzenie tej flagi? – vach

+1

@Vach 'InterruptedException' jest zaznaczonym wyjątkiem. Kompilator wie, kiedy może i nie może być rzucony. W twoim kodzie nic nie może go wyrzucić, więc nie ma mowy, żebyś mógł go złapać. –

+1

@Vach Tak, sprawdź flagę w odpowiednich momentach wykonania i podejmij stosowne działania. –

Powiązane problemy