Kushal
Kushal

Reputation: 3168

End execution of Thread without using its stop() method

I have a Swing form with a button, which is when clicked starts SocketServer for listening to incoming requests in a separate thread. Following is structure of classes I have.

Following is Start button's Click Event Body.

t = new Thread(new Runnable() //Object t is created globally in this main class.
{
    public void run()
    {
        myss = new MySocketServer(); //Object myss has similar accessibility as t.
        myss.startServer();
    }
});
t.start();

And Following is Stop Button's Click Event Body

myss.stopServer();
if(t.isAlive());
    System.out.println("Thread is still alive!!");

Though I can toggle SockeServer "start" and "stop" as my times I want, but I realize that everytime I start the server, new thread gets created and it remains active even though server is stopped using MySocketServer's method.

I can use stop() of Thread and stop the thread execution but since it is depreciated and I have studied that threads get ended once their run() method has executed completely, but I have startServer() method separated so that it can handle connected clients separately.

Please note that startServer() has While-Listen loop, so essentially run() method of thread is in infinite state of execution, until I explicitly call stopServer() and halt the loop.

what can be done here?

Upvotes: 0

Views: 858

Answers (3)

Stephen C
Stephen C

Reputation: 719229

Firstly, you are right to not try to use Thread.stop(). It is potentially dangerous.

So what should you do?

One possibility might to be to write your server thread like this:

    ....
    ServerSocket ss = new ServerSocket(...);
    try {
       while (keepGoing) {
           Socket s = ss.accept(...);
           try {
               // do stuff
           } finally {
               // close socket
           }
       }
    } finally {
       // close the server socket
    }

and have stopServer clear the keepGoing flag. But the problem is that the stop typically will come while the thread is blocked in the accept call, and there's nothing to unblock it.

Another possibility might be to call Thread.interrupt() on the thread. That causes some things to unblock, and throw an exception, but I don't think it will unblock the accept() call though. (However, this is still better than setting a flag if the "do stuff" part needs interrupting.)

The real solution (I think) is to close the ServerSocket. This will cause the ss.accept() call to unblock and throw an exception, which you need to handle in the server thread.

Upvotes: 1

Viktor Stolbin
Viktor Stolbin

Reputation: 2939

You shouldn't use stop(). Take a look at this http://docs.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html The solution with infinite loop and start/stop flags is straightforward but leads to ineffective using of CPU time. The better way is to use wait/notify approach. The way you operate with MySocketServer gives me feeling that you have other infinite loop inside the startServer(). That's why you have to stop it. It would be better to wrap this loop into it's own thread internally and make start/stop methods operate with this thread state in wait/notify manner. Forgot to mention, as your GUI runs in its own thread you can't escape start/stop flag inside the MySocketServer because using wait() in GUI thread will make it hanged.

Upvotes: 0

paulm
paulm

Reputation: 5892

In your MySocketServer class in the while loop you need a flag which will test if it should keep running or not.

In your newly added shutdown method set the flag which the loop in the thread will test. Once the loop breaks and run() returns the thread will end.

Upvotes: 0

Related Questions