2016-04-20 31 views
2

第一個問題在這裏StackOverflow,所以請原諒我,如果我不正確地問。Java:多線程與兩個不同的輸入源和反應

基本上,我正在編寫一個多播客戶端,它無限期地監聽多播地址,直到用戶在控制檯輸入「quit」。我發現爲MulticastSocket設置SO_TIMEOUT,檢查是否鍵入了「quit」,然後返回到receive方法調用並不真正起作用,因爲可以在超時和檢查控制檯塊後立即發送數據包。所以我相信最好的選擇是隻要有2個線程在其中一個監聽套接字並阻塞,直到它收到一些東西,而另一個線程監聽控制檯直到被告知退出。我唯一的問題是我不確定如何去控制檯監聽線程告訴套接字線程關閉套接字並終止。 System.end()會工作,但我擔心我會留下一個插座打開等。

TLDR;有沒有辦法讓一個類的主要方法啓動一個線程,然後在線程結束後以特定的方式響應?我需要在一個線程上監聽控制檯,在另一個線程上監聽MulticastSocket,或者僅在客戶端類的主體中監聽。

謝謝大家。

回答

1

我打電話給Socket.close()關閉插座。這將在該線程中產生IOException。所以在這之前,我會設置一個像closed = true;這樣的標誌,並讓其他線程在打印錯誤之前檢查它,即如果您已關閉,請不要打印IOException。像這樣的東西。

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(); 
    } 
} 

例如,在你的主線程可以做

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

有點困惑在這裏。從控制檯讀取的線程如何與套接字偵聽器的關閉進行交互?我認爲對於我自己的代碼,我會讓我的客戶端實現Runnable接口,但我只是有點不確定你打算如何交互這兩個線程。如果我的問題看起來很平凡,我並沒有在線程方面做太多的事情。 – user16728

+0

@ user16728您有控制檯讀取線程調用'close()'方法。 –

+0

@ user16728我爲我的答案添加了一個示例。 –

相關問題