2016-04-20 10 views
2

Erste Frage hier auf StackOverflow, also bitte entschuldigen Sie, wenn ich das falsch frage.Java: Multithreading mit zwei verschiedenen Eingabequellen und reagieren

Grundsätzlich schreibe ich einen Multicast-Client, der unbegrenzt auf eine Multicast-Adresse hört, bis der Benutzer "quit" in die Konsole eingibt. Ich habe festgestellt, dass SO_TIMEOUT für die MulticastSocket gesetzt, zu prüfen, ob "quit" eingegeben wurde, und dann zurück zu der Empfangsmethode Aufruf funktioniert nicht wirklich, da ein Paket direkt nach dem Timeout und der Überprüfung der Konsolenblöcke gesendet werden könnte . Also glaube ich, dass die beste Option ist, einfach 2 Threads zu haben, wo man auf den Socket hört und blockt, bis er etwas empfängt, und der andere Thread hört auf die Konsole, bis man sagt, dass er aufhören soll. Das einzige Problem, das ich habe, ist, dass ich mir nicht sicher bin, wie ich den Konsolen-Überwachungsthread dazu bringen soll, dem Socket-Thread mitzuteilen, dass er den Socket schließen und beenden soll. System.end() würde funktionieren, aber ich befürchte, dass ich einen Sockel offen lassen würde usw.

TLDR; Gibt es eine Möglichkeit für die Hauptmethode einer Klasse, einen Thread zu starten und dann auf eine bestimmte Weise zu antworten, sobald dieser Thread beendet ist? Ich muss die Konsole auf einem Thread und einem MulticastSocket auf einem anderen oder nur in der Hauptklasse der Client-Klasse hören.

Danke an alle.

Antwort

1

Ich würde Socket.close() anrufen, um den Sockel zu schließen. Dies erzeugt eine IOException in diesem Thread. Bevor ich das mache, würde ich ein Flag wie closed = true; setzen und den anderen Thread überprüfen lassen, bevor ich den Fehler drucke, d. h. keine IOException drucken, wenn Sie geschlossen wurden. Etwas wie das.

public class SocketListener implements Runnable, Closeable { 
    final MulticastSocket socket; 
    final Consumer<DatagramPacket> packetConsumer; 
    volatile boolean closed; 

    public SocketListener(MulticastSocket socket, Consumer<DatagramPacket> packetConsumer) { 
     this.socket = socket; 
     this.packetConsumer = packetConsumer; 
    } 

    @Override 
    public void run() { 
     DatagramPacket packet = new DatagramPacket(new byte[1024], 1024); 
     try { 
      while(!closed) { 
       socket.receive(packet); 
       packetConsumer.accept(packet); 
      } 
     } catch (IOException e) { 
      if (!closed) 
       e.printStackTrace(); 
     } 
    } 

    @Override 
    public void close() throws IOException { 
     closed = true; 
     socket.close(); 
    } 
} 

zum Beispiel in Ihrem Haupt-Thread können Sie

MulticastSocket socket = ... 
Consumer<DatagramPacket> packetConsumer = ... 
try (SocketListener listener = new SocketListener(socket, packetConsumer)) { 
    boolean finished = false; 
    do { 
     // read from the console 
     if (some condition) 
      finished = true; 
    } while(!finished); 
} // calls close() for you. 
+0

Ein wenig verwirrt hier tun. Wie würde der Thread, der von der Konsole liest, mit dem Schließen des Socket-Listeners interagieren? Ich denke, für meinen eigenen Code würde ich meinen Client die Runnable-Schnittstelle implementieren lassen, aber ich bin nur ein wenig unsicher, wie Sie die Interaktion der beiden Threads beabsichtigen. Ich habe nicht viel getan mit Entschuldigungen, wenn meine Fragen banal erscheinen. – user16728

+0

@ user16728 Sie haben die Konsole lesen Thread rufen Sie die 'close()' Methode. –

+0

@ user16728 Ich habe ein Beispiel zu meiner Antwort hinzugefügt. –