Jak natychmiast zakończyć blokadę wątku przy operacji socket IO?

W kontekście Javy, tworzę nowy wątek do odczytu wejścia sieciowego, gdy otwieram okno GUI, a kiedy zamykam okno, chcę zwolnić zasób gniazda i natychmiast zakończyć wątek. Teraz używam metody setSoTimeout, ale nie chcę czekać na wyjątek timeout. Czy ktoś może coś zasugerować? Dzięki!

Author: Dingxin Xu, 2010-12-13

2 answers

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

  • Calling Socket.close() na gnieździe zamkną powiązane obiekty InputStream i OutputStream i spowodują odblokowanie wątków zablokowanych w gnieździe lub (powiązanych) operacjach strumienia. Według javadoc, operacje na samym gnieździe spowodują SocketException.

  • Wywołanie Thread.interrupt() spowoduje (w pewnych okolicznościach, które nie są określone) przerwanie blokującej operacji We/Wy, powoduje, że rzuca InterruptedIOException.

    zwróć uwagę na zastrzeżenie. Najwyraźniej podejście "interrupt ()" nie działa na "większości" nowoczesnych platform Java. (Gdyby ktoĹ "inny miaĹ' czas i inklinacjä™, moĹĽe zbadaÄ ‡ okolicznoĹ "ci w jakich to podejĹ" cie dziaĹ ' a. Jednak sam fakt, że zachowanie jest specyficzne dla platformy, powinien wystarczyć, aby powiedzieć, że powinieneś go używać tylko wtedy, gdy potrzebujesz tylko swojej aplikacji do pracy na określonej platformie. W którym momencie możesz łatwo "spróbuj" dla siebie.)

  • Ewentualnym trzecim sposobem na to jest wywołanie Socket.shutdownInput() i / lub Socket.shutdownOutput(). Javadoc nie mówią wprost, co dzieje się z blokowanymi operacjami odczytu i/lub zapisu, ale nie jest nieuzasadnione myślenie, że odblokują i wyrzucą wyjątek. Jeśli jednak javadoc nie powie, co się dzieje, należy przyjąć, że zachowanie to jest specyficzne dla platformy.

 60
Author: Stephen C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-21 00:14:35

Wiem, że to pytanie jest stare, ale ponieważ wydaje się, że nikt nie rozwiązał "tajemnicy" Thread.interrupt() na "nowoczesnych platformach", poszperałem trochę.

Jest to testowane na Javie 8 na Windows7 (64-bit) (ale prawdopodobnie będzie to prawdą również dla innych platform).

Wywołanie Thread.interrupt() robi nie rzuca InterruptedIOException Dzieje się tak, że metoda InputStream.read() zwraca z -1 i Thread.interrupted()-flaga jest ustawiona.

Więc można uznać za "poprawione" read () 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;
}
 18
Author: raudi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-18 15:37:20