2010-12-13 14 views
61

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

+11

Je ne comprends pas pourquoi cela a -1?!? Je pense que la question était très claire et sur place. –

Répondre

53

Il y a (potentiellement) trois façons de le faire:

  • Appel Socket.close() sur la prise fermera les objets InputStream et OutputStream associés, et provoquer des threads bloqués dans les opérations de flux Socket ou (associé) à être débloqué. Selon le javadoc, les opérations sur le socket lui-même vont lancer un SocketException.

  • L'appel Thread.interrupt() (dans certaines circonstances non spécifiées) interrompt une opération d'E/S de blocage, provoquant l'envoi d'un InterruptedIOException.

    Notez la mise en garde. Apparemment, l'approche "interruption()" ne fonctionne pas sur "la plupart" des plates-formes Java modernes. (Si quelqu'un d'autre avait le temps et l'envie, ils pourraient enquêter sur les circonstances dans lesquelles cette approche fonctionne.Mais le simple fait que le comportement est spécifique à la plate-forme devrait suffire à dire que vous ne devriez l'utiliser que si vous avez seulement besoin de votre application de travailler sur une plate-forme spécifique. a quel point vous pouvez facilement « essayer » pour 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'ils vont se débloquer et lancer une exception. Cependant, si le javadoc ne dit pas ce qui se passe alors le comportement devrait être supposé être spécifique à la plate-forme.

+1

Dans quelles circonstances thread.interrupt() interrompt-il une opération d'E/S de blocage? –

+2

Xu DXn - ce n'est pas documenté. Certains flux implémentent cela, d'autres non. Pour les détails sanglants, lisez le code source OpenJDK. Ce que j'essaie de dire, c'est que cela peut fonctionner ou non. –

+1

assez sûr que la plupart des implémentations jvm ne supportent pas les opérations io interruptibles. Je pense que peut-être le sun solaris jvm l'a soutenu à un moment donné. – jtahlborn

12

Je sais que cette question est vieux, 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 a été testé sur Java 8 sous Windows7 (64 bits) (mais cela pourrait aussi être vrai pour d'autres plateformes).

Appel Thread.interrupt() ne pas jeter un InterruptedIOException Ce qui se passe est que la méthode InputStream.read() revient avec -1 et Thread.interrupted() -flag est réglé.

Ainsi, les éléments suivants peuvent être considérés comme une lecture() 'corrigé' jetant 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

Cette réponse mérite plus de votes parce que le comportement de Java lorsqu'il est interrompu pendant les opérations de flux Entrée/Sortie n'est pas ce que beaucoup de gens attendent. –