2016-11-14 23 views
1

現在、私はJavaネットワークライブラリで作業しており、DatagramSocketの問題に直面しています。私はUDPリクエストを聞き続けているスレッドを持っていて、それを止めて関連するDatagramSocketを閉じると、とにかく止まらないスレッドがあります。ここでDatagramSocketスレッドを停止する

は、問題を再現するコードサンプルです:

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.SocketException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

class UDPListener implements Runnable { 

    private volatile boolean isRunning; 
    private volatile boolean clientClosed; 
    private int port; 
    private DatagramSocket client; 

    public UDPListener(int listeningPort) { 
     this.port = listeningPort; 
    } 

    public void open() throws SocketException { 
     this.clientClosed = false; 
     if (this.client != null) { 
      this.client.close(); 
     } 
     this.client = new DatagramSocket(this.port); 
    } 

    @Override 
    public void run() { 
     this.isRunning = true; 
     this.clientClosed = false; 
     DatagramPacket packet = new DatagramPacket(new byte[256], 256); 
     while (this.isRunning) { 

      try { 
       this.client.receive(packet); 
      } catch (SocketException e) { 
       if (!this.clientClosed) { 
        e.printStackTrace(); 
       } 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
     this.client.disconnect(); 
     System.out.println("stopped"); 
    } 

    public void stop() { 
     this.isRunning = false; 
     this.clientClosed = true; 
     this.client.close(); 
    } 


    public static void main(String[] args) throws InterruptedException, SocketException { 
     UDPListener t = new UDPListener(0); 
     ExecutorService e = Executors.newFixedThreadPool(1); 
     t.open(); 
     e.submit(t); 
     Thread.sleep(1000); 
     t.stop(); 
    } 
} 

私はセレクタクラスと同じ問題を抱えています。

私は間違っていますか?

+0

私が:(私の質問に明確ではなかったようだスレッドがエグゼキュータを開始する「(停止します「停止」が表示されます)、明示的に開始しなかったスレッドがバックグラウンドで実行され続け、使用されているポートを残してアプリケーションが終了しないようにします – Maliafo

答えて

2

ExecutorService#shutdownNow()メソッドへの呼び出しを含めるのを忘れました。

コードを少しリファクタリングして基本的なロギングステートメントを追加して、コードが何をより良くしているかを視覚化できるようにしました。

は、ここでの出力例です:

javac UDPListener.java && java UDPListener 
[main] Started main application. 
[main] Sleeping for 2000 
[pool-1-thread-1] Starting... 
[pool-1-thread-1] Opening datagram socket... 
[pool-1-thread-1] Opened datagram socket. 
[pool-1-thread-1] Waiting for datagrams... 
[main] Slept for 2000 
[main] Stopping all threads. 
[pool-1-thread-1] Interrupted while waiting for datagrams. 
[pool-1-thread-1] Stopped. 
[main] Stopped main application. 

固定コードは以下の通りです:。

import java.io.IOException; 
import java.net.DatagramPacket; 
import java.net.DatagramSocket; 
import java.net.SocketException; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

class UDPListener implements Runnable { 

    private volatile boolean isRunning; 
    private volatile boolean clientClosed; 
    private int port; 
    private DatagramSocket client; 

    public UDPListener(int listeningPort) { 
     this.port = listeningPort; 
    } 

    private void open() throws SocketException { 
     System.out.println(getName() + " Opening datagram socket..."); 
     this.clientClosed = false; 
     if (this.client != null) { 
      this.client.close(); 
     } 
     this.client = new DatagramSocket(this.port); 
     System.out.println(getName() + " Opened datagram socket."); 
    } 

    @Override 
    public void run() { 
     System.out.println(getName() + " Starting..."); 
     try { 
      this.open(); 

      this.isRunning = true; 
      this.clientClosed = false; 
      final DatagramPacket packet = new DatagramPacket(new byte[256], 256); 

      while (this.isRunning) { 
       System.out.println(getName() + " Waiting for datagrams..."); 
       try { 
        this.client.receive(packet); 
       } catch (SocketException e) { 
        if (!this.clientClosed) { 
         e.printStackTrace(); 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } finally { 
        System.out.println(getName() + " Interrupted while waiting for datagrams."); 
       } 
      } 
     } catch (SocketException se) { 
      se.printStackTrace(); 
     } finally { 
      this.client.disconnect(); 
      System.out.println(getName() + " Stopped."); 
     } 
    } 

    public void stop() { 
     this.isRunning = false; 
     this.clientClosed = true; 
     this.client.close(); 
    } 

    private static String getName() { 
     return "[" + Thread.currentThread().getName() + "]"; 
    } 


    public static void main(String[] args) throws InterruptedException, SocketException { 
     System.out.println(getName() + " Started main application."); 
     UDPListener t = new UDPListener(0); 
     ExecutorService e = Executors.newFixedThreadPool(1); 
     // t.open(); easier to debug if this call is exclusively done by UDPListener#run() 
     e.submit(t); 
     final int sleep = 2000; 
     System.out.printf(getName() + " Sleeping for %d\n", sleep); 
     Thread.sleep(sleep); 
     System.out.printf(getName() + " Slept for %d\n", sleep); 
     System.out.println(getName() + " Stopping all threads."); 
     t.stop(); 
     e.shutdownNow(); 
     System.out.println(getName() + " Stopped main application."); 
    } 
} 
関連する問題