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!
2 answers
Istnieją (potencjalnie) trzy sposoby, aby to zrobić:
Calling
Socket.close()
na gnieździe zamkną powiązane obiektyInputStream
iOutputStream
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 rzucaInterruptedIOException
.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 / lubSocket.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.
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;
}
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