2

ServerSocket と Sockets をより適切に制御するために非常に基本的な API を実装していますが、スレッドに関する知識がないために修正できない非常に奇妙な問題に直面しています。説明させてください。

私のクラス SocketStreamReceiver では、セカンダリ スレッドを使用して新しいソケットをリッスンしServerSocket#accept()ます。クライアントが SocketStreamReceiver を開始 (スレッドを作成してリッスンを開始accept()) および停止 (ServerSocket を閉じてスレッドを破棄) するために使用できる start() と stop() の 2 つのメソッドがあります。

stop() メソッドをどのように実装しますか? stop() は、doSomething() 内で、start() によって開始された同じセカンダリ スレッドで呼び出すことができることに注意してください。好きなように変更できます。必要に応じて、while(running) の直前に、スレッド内に ServerSocket を作成できます。

public class SocketStreamReceiver{
    ...
    private Thread thread;
    private ServerSocket server;
    private boolean running;
    ...

    public void start () throws IOException{
        if (thread != null) return;

        server = new ServerSocket (port);
        thread = new Thread (new Runnable (){
            @Override
            public void run (){
                try{
                    while (running){
                        Socket socket = server.accept ();
                        doSomething (socket);
                    }
                }catch (SocketException e){
                    ...
                }catch (IOException e){
                    ...
                }
            }
        }, "SocketStreamReceiver");
        thread.start ();
    }

    public void stop () throws IOException{
        if (thread == null) return;

        //code...

        thread = null;
    }
}

ありがとう。

編集 - 解決策:

public class SocketStreamReceiver{
    private Thread thread;
    private ServerSocket server;
    private volatile boolean running;
    ...

    public synchronized void start () throws IOException{
        if (thread != null) throw new IllegalStateException ("The receiver is already started.");

        server = new ServerSocket (port);
        thread = new Thread (new Runnable (){
            @Override
            public void run (){
                try{
                    running = true;
                    while (running){
                        doSomething (server.accept ());
                        ...
                    }
                }catch (SocketException e){
                    ...
                }catch (IOException e){
                    ...
                }
            }
        }, "SocketStreamReceiver");
        thread.start ();
    }

    public synchronized void stop (){
        if (thread == null) return;

        running = false;
        try{
            if (server != null){
                server.close ();
            }
        }catch (IOException e){}

        thread = null;
    }
}
4

1 に答える 1

4

私はただするだろう

public void stop() {
    running = false;
    try{
        if (server != null) server.close ();
    } catch (IOException ignored){
    }
}

実行中のフラグさえ必要ないようです。ただし、サーバーの受け入れコードで使用して、例外が予想されるかどうかを判断します。つまり、== false を実行すると、すべての例外が無視されます。

私はrunning揮発性にします。

これらを異なるスレッドから実行できる場合は、 start()/stop() を同期させます。

于 2011-04-14T08:31:41.350 に答える