Остановка потока цикла ServerSocket accept () - PullRequest
1 голос
/ 14 апреля 2011

Я реализую очень простой API, чтобы лучше контролировать ServerSocket и Sockets, но у меня очень странная проблема, которую я не могу исправить из-за недостатка знаний о потоках. Позвольте мне объяснить это.

В моем классе SocketStreamReceiver я использую вторичный поток для прослушивания новых сокетов с ServerSocket#accept(). Существует 2 метода: start () и stop (), которые клиент может использовать для запуска (создания потока и начала прослушивания с accept()) и остановки (закрытия ServerSocket и уничтожения потока) моего SocketStreamReceiver.

Как вы реализуете метод stop ()? Имейте в виду, что stop () может вызываться внутри doSomething () в том же вторичном потоке, который запускается start (). Вы можете изменить все, что хотите: вы можете создать 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;
    }
}

1 Ответ

2 голосов
/ 14 апреля 2011

Я бы просто сделал

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

Похоже, вам даже не нужен флаг запуска. Однако я бы использовал его на вашем сервере, чтобы принять код, чтобы определить, ожидается ли исключение или нет. т.е. при запуске == false игнорировать все исключения.

Я бы сделал running изменчивым.

Я бы синхронизировал start () / stop (), если вы можете запускать их из разных потоков.

...