Stopping a ServerSocket accept() loop thread
I'm implementing a very basic API to have a better control over ServerSocket and Sockets, but I'm in a very weird problem that I cannot fix due to my lack of threads knowledge. Let me explain it.
In my class SocketStreamReceiver I use a secondary thread to listen for new sockets with ServerSocket#accept()
. There are 2 methods: start() and stop() that the client can use to start (creating a thread and begin listening with accept()
) and stop (closing the ServerSocket and dest开发者_StackOverflow社区roying the thread) my SocketStreamReceiver.
How will you implement stop() method? Keep in mind that stop() can be called inside doSomething(), in the same secondary thread started by start(). You can change anything you want: you can create the ServerSocket inside the thread if you want, just before while(running).
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;
}
}
Thanks.
EDIT - Solution:
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;
}
}
I would just do
public void stop() {
running = false;
try{
if (server != null) server.close ();
} catch (IOException ignored){
}
}
It doesn't appear you even need the running flag. However I would use it in your server accept code to determine if an Exception is expected or not. i.e. when running == false ignore all exceptions.
I would make running
volatile.
I would make start()/stop() synchronized if you can run these from different threads.
精彩评论