web-dev-qa-db-fra.com

Comment mettre fin à un blocage de thread sur le socket IO opération instantanément?

Dans le contexte de Java, je crée un nouveau thread pour lire l'entrée réseau lorsque j'ouvre une fenêtre GUI, et quand je ferme la fenêtre, je veux libérer la ressource socket et terminer immédiatement le thread. Maintenant j'utilise la méthode setSoTimeout, mais je ne veux pas attendre l'exception de timeout. Quelqu'un pourrait-il faire une suggestion? Merci!

65
Dingxin Xu

Il existe (potentiellement) trois façons de procéder:

  • L'appel Socket.close() sur le socket fermera les objets InputStream et OutputStream associés et provoquera le blocage de tous les threads dans les opérations de flux Socket ou (associées) être débloqué. Selon le javadoc, les opérations sur le socket lui-même lanceront un SocketException .

  • L'appel Thread.interrupt() interrompra (dans certaines circonstances qui ne sont pas spécifiées) une opération d'E/S bloquante, provoquant un InterruptedIOException =.

    Notez la mise en garde. Apparemment, l'approche "interruption ()" ne fonctionne pas sur la plupart des plates-formes modernes Java. (Si quelqu'un d'autre avait le temps et l'inclinaison, il pourrait éventuellement enquêter sur les circonstances dans lesquelles cette approche fonctionne). . Cependant, le simple fait que le comportement soit spécifique à la plate-forme devrait suffire à dire que vous ne devez l'utiliser que si vous avez uniquement besoin que votre application fonctionne sur une plate-forme spécifique. À ce stade, vous pouvez facilement "l'essayer" par vous-même.)

  • Une troisième façon possible de le faire est d'appeler Socket.shutdownInput() et/ou Socket.shutdownOutput() . Les javadocs ne disent pas explicitement ce qui se passe avec les opérations de lecture et/ou d'écriture qui sont actuellement bloquées, mais il n'est pas déraisonnable de penser qu'elles débloqueront et lèveront une exception. Cependant, si le javadoc ne dit pas ce qui se passe, le comportement doit être supposé être spécifique à la plate-forme.

55
Stephen C

Je sais que cette question est ancienne mais comme personne ne semble avoir résolu le "mystère" de Thread.interrupt() sur les "plates-formes modernes", j'ai fait quelques recherches.

Ceci est testé sur Java 8 sur Windows7 (64 bits) (mais cela sera peut-être également vrai pour d'autres plates-formes).

L'appel de Thread.interrupt() fait pas lancer un InterruptedIOException Ce qui se passe est que la méthode InputStream.read() retourne avec -1 Et Thread.interrupted()- est défini.

Ainsi, ce qui suit pourrait être considéré comme un read () corrigé lançant 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;
}
16
raudi