2010-12-13 13 views
61

W kontekście Java, tworzę nowy wątek do odczytu wejścia sieciowego po otwarciu okna GUI, a kiedy zamknę okno, chcę zwolnić zasób gniazda i natychmiast zakończyć wątek. Teraz używam metody setSoTimeout, ale nie chcę czekać wyjątek timeout. Czy ktokolwiek mógłby dać jakąś sugestię? Dzięki!Jak natychmiast zakończyć blokowanie wątków w operacji gniazda IO?

+11

ja nie rozumiem, dlaczego to ma -1?!? Myślę, że pytanie było dość jasne i na miejscu. –

Odpowiedz

53

Są to (potencjalnie) trzy sposoby, aby to zrobić:

  • Wywołanie Socket.close() na gnieździe zamknie związane InputStream i OutputStream przedmiotów i powodować żadnych wątków zablokowanych w gniazda lub operacji (związany) strumień być odblokowanym. Zgodnie z javadoc operacje na samym gnieździe wyrzucą SocketException.

  • Wywołanie spowoduje (w pewnych okolicznościach, które nie są określone) przerwać operację blokowania I/O, powodując, że rzuca ona InterruptedIOException.

    Uwaga na zastrzeżenie. Najwyraźniej metoda "interrupt()" nie działa na "większości" nowoczesnych platform Java. (Jeśli ktoś miałby czas i skłonność, mógłby zbadać okoliczności, w których to podejście działa, ale sam fakt, że zachowanie jest specyficzne dla danej platformy, powinien wystarczyć, aby powiedzieć, że powinieneś go używać tylko wtedy, gdy potrzebujesz tylko swojej aplikacji do pracy na określonym platformy. w tym momencie można łatwo „wypróbować” dla siebie.)

  • Ewentualny trzeci sposób to zrobić, to zadzwonić Socket.shutdownInput() i/lub Socket.shutdownOutput(). Javadocs nie mówią jednoznacznie, co dzieje się z operacjami odczytu i/lub zapisu, które są obecnie zablokowane, ale nie jest nierozsądne myślenie, że odblokują one i wyrzucą wyjątek. Jeśli jednak javadoc nie powie, co się stanie, należy przyjąć, że zachowanie jest specyficzne dla danej platformy.

+1

Proszę, w jakich okolicznościach threadinterterrupt() przerwie blokowanie operacji we/wy? –

+2

Xu DXn - nie jest to udokumentowane. Niektóre strumienie realizują to, inne nie. Aby poznać szczegóły, przeczytaj kod źródłowy OpenJDK. Chodzi mi o to, że może działać, ale nie musi. –

+1

całkiem pewnie większość implementacji jvm nie _pomaga obsługiwać operacji przerywalnych io. Myślę, że być może sun solaris jvm wspierał go w pewnym momencie. – jtahlborn

12

Wiem, że to pytanie jest stary, ale jak nikt nie wydaje się być rozwiązany „tajemnicę” Thread.interrupt() na „nowoczesnych platform” Zrobiłem rozeznanie.

Zostało to przetestowane na Javie 8 na Windows7 (64-bit) (ale może się to również sprawdzić na innych platformach).

Wywołanie Thread.interrupt() robi nie rzucać InterruptedIOException Co się dzieje, jest to, że metoda InputStream.read() powraca z -1 i Thread.interrupted() FLAG jest ustawiony.

Więc dodaje można uznać za 'poprawione' read() rzuca InterruptedIOException:

static final int read(Socket socket, byte[] inData) 
    throws SocketTimeoutException, // if setSoTimeout() was set and read timed out 
      InterruptedIOException, // if thread interrupted 
      IOException    // other erors 
{ 
    InputStream in = socket.getInputStream(); 

    int readBytes = in.read(inData, 0, inData.length); 

    if (Thread.interrupted()) 
    { 
     throw new InterruptedIOException("Thread interrupted during socket read"); 
    } 

    return readBytes; 
} 
+1

Ta odpowiedź zasługuje na więcej głosów, ponieważ zachowanie Java podczas przerw w działaniu strumienia wejścia/wyjścia nie jest tym, czego wielu ludzi się spodziewa. –

Powiązane problemy