2011-08-20 2 views
4

Cette question a sans doute été posée sous diverses formes dans le passé, mais pas tellement pour un scénario spécifique.Quelle est la manière correcte d'arrêter un thread en attente d'une activité réseau?

Quelle est la manière la plus correcte d'arrêter un thread qui bloque en attendant de recevoir un message réseau via UDP.

Par exemple, dire que j'ai le fil suivant:

public class ClientDiscoveryEngine extends Thread { 

    private final int PORT; 

    public ClientDiscoveryEngine(final int portNumber) { 
     PORT = portNumber; 
    } 

    @Override 
    public void run() { 
     try { 
      socket = new DatagramSocket(RECEIVE_PORT); 

      while (true) { 
       final byte[] data = new byte[256]; 
       final DatagramPacket packet = new DatagramPacket(data, data.length); 

       socket.receive(packet); 
      } 
     } catch (SocketException e) { 
      // do stuff 1 
     } catch (IOException e) { 
      // do stuff 2 
     } 
    } 
} 

Maintenant, serait la façon plus correcte soit en utilisant la méthode interrupt()? Par exemple en ajoutant la méthode suivante:

@Override 
public void interrupt() { 
    super.interrupt(); 
    // flip some state? 
} 

Mon seul souci est, est socket.receive() pas une méthode de blocage non interruptible? La façon dont j'ai pensé serait de mettre en œuvre la méthode d'interruption comme ci-dessus, dans cette méthode appelez socket.close() et ensuite prendre en charge dans la méthode run dans le catch pour le SocketException. Ou peut-être au lieu de while(true) utiliser un état qui est retourné dans la méthode d'interruption. Est-ce la meilleure façon? Ou y a-t-il une manière plus élégante?

Merci

Répondre

4

La méthode receive ne semble pas être interruptible. Vous pouvez fermer le socket: le javadoc dit:

Tout thread actuellement bloqué dans receive(java.net.DatagramPacket) sur cette prise lancera une SocketException

Vous pouvez également utiliser setSoTimeout pour faire le bloc de réception de la méthode que pour un petite quantité de temps. Après que la méthode est revenue, votre thread peut vérifier s'il a été interrompu, et réessayer de recevoir à nouveau pendant ce petit laps de temps.

2

Pour arrêter un fil, vous ne devriez pas l'utilisateur ni interrompre ni arrêter en java. La meilleure façon, comme vous l'avez suggéré à la fin de votre question, est d'avoir la boucle à l'intérieur de la méthode principale contrôlée par un drapeau que vous pouvez augmenter au besoin.

Voici un vieux lien à ce sujet: http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html

D'autres façons d'arrêter un fil sont dépréciée et ne fournissent pas autant de contrôle que celui-ci. En outre, cela a peut-être changé un peu avec les services d'exécution, je n'ai pas encore eu le temps d'en apprendre beaucoup à ce sujet.

De même, si vous voulez éviter que votre thread ne soit bloqué dans certains états d'E/S, en attendant un socket, vous devez accorder une connexion et un temps de lecture à votre socket (méthode setSoTimeout).

Cordialement, Stéphane

+1

Err, non. l'interruption est là pour arrêter un fil.C'est en fait le seul moyen de le faire si le thread peut être bloqué dans un appel bloquant qui réagit aux interruptions (comme Thread.sleep, Object.wait, lire depuis un canal interruptible, etc.). Lisez http://download.oracle.com/javase/tutorial/essential/concurrency/interrupt.html. –

0

Ceci est l'un des plus faciles. S'il est bloqué sur un socket UDP, envoyez au socket un message UDP qui indique au thread de réception d'arrêter.

Mfg, Martin

Questions connexes