This week's book giveaway is in the OCMJEA forum.
We're giving away four copies of OCM Java EE 6 Enterprise Architect Exam Guide and have Paul Allen & Joseph Bambara on-line!
See this thread for details.
The moose likes Threads and Synchronization and the fly likes stopping a thread (runable) Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of OCM Java EE 6 Enterprise Architect Exam Guide this week in the OCMJEA forum!
JavaRanch » Java Forums » Java » Threads and Synchronization
Bookmark "stopping a thread (runable)" Watch "stopping a thread (runable)" New topic
Author

stopping a thread (runable)

Nate Lockwood
Ranch Hand

Joined: Feb 22, 2010
Posts: 83
I have been attempting to write a socket server and its companion a client (learning about threads and sockets in the process) I now have them working (under LINUX but not OS X) but need to catch and process unexpected disconnects.

When a connection is made on either the client or master two threads: a new instance of a talkWorker which sends messages to the remote and listenWorker which receives messages from a remote are created and started with threadPoolExecutors.

Both the listenWorker and talkWorker threads are in loops and I have a Boolean sentinel "isConnected" controlling the loop. Since I can catch the exception thrown in listenWorker by the socket on a disconnect I can just set the sentinel to false and the thread stops looping.

Question: does this thread then die or does it just languish in some sort of cyber purgatory? Will I need to call garbage collection at this point?

The other thread, talkWorker is blocked waiting to take data from a blocking queue and then write to the socket. I have not seen an exception thrown here (although I think it might be if it tried to write data to a disconnected socket). Since no exception is caught I can't use the sentinel

Questiion: how do I signal it to stop? Would I send an interrupt to it from listenWorker? I can catch that exception I think.

I expect that I will also need to close the socket so I don't bleed resources. Do I make it null, too? Do I need to do anything with the threadpool executors or will they detect this automatically.

Of course this must be done with the expectation that the computer whose connection went down will come back on line and attempt to reconnect.

Steve Luke
Bartender

Joined: Jan 28, 2003
Posts: 4181
    
  21

Nate Lockwood wrote:Question: does this thread then die or does it just languish in some sort of cyber purgatory? Will I need to call garbage collection at this point?


That depends a little. As long as you can reliably say the run() method comes to an end (this is your code so only you can answer this), then what happens to the Thread that runs the Runnable is dependent on your ThreadPoolExecutor. Depending on the configuration, the Thread may hang around in a pool to be used later on by another request to run via the same ThreadPoolExecutor. Or it could get destroyed by the Executor right away, or after some period of time. What you have to worry about is that the run() method comes to an end, and that no resources are left stored in the Thread (for example any ThreadLocal references are cleared).

The other thread, talkWorker is blocked waiting to take data from a blocking queue and then write to the socket. I have not seen an exception thrown here (although I think it might be if it tried to write data to a disconnected socket). Since no exception is caught I can't use the sentinel
Questiion: how do I signal it to stop? Would I send an interrupt to it from listenWorker? I can catch that exception I think.

There are a couple of ways to do this. One way is to interrupt the talkWorker's thread, catch the exception and check the sentinel status. If the status is set to false, then stop listening and break out of the loop. Otherwise report the exception and try again. This may require some work (a method on talkWorker like 'stop()' which sets isConnected to false then uses a reference to the thread running the run() method to interrupt it, and passing a reference to the talkWorker to whomever knows when the process should stop).

Since you already have a communication channel between the talkWorker and the listenWorker (the blocking queue I think) then you could use a different approach - one that is called a 'Poison Pill'. You create a specific Object and pass it both to the producer (whomever sends data to the blocking queue) and the consumer (the talkWorker). When the producer wants the consumer to stop working you send the Poison Pill onto the Queue. On the consumer side the consumer reads from the queue and the first thing it does is compare what it gets to the Poison Pill (using == since you want to make sure the identity of the Object is exact). If they are equal the talkWorker doesn't try to send anything to down the socket, it instead breaks out of the loop and shuts down.


I expect that I will also need to close the socket so I don't bleed resources.
Yes, do this in a finally block so it gets shut down no matter what, but also surround it in a try/catch since closing can fail if something else caused it to close already (which if you are not careful could hide other exceptions).
Do I make it null, too?
That depends on scope. You should be keeping the reference in the smallest scope possible, so when it closes either it goes out of scope (and so doesn't need to be set to null). Don't create references to it that aren't necessary, and let your Objects which do reference it come to a natural death (don't hold references to them, don't try to make the re-runnable, make sure their methods all come to an end safely).

Do I need to do anything with the threadpool executors or will they detect this automatically.
Just in the case of an exception in one thread? That depends on your philosophy and how well you think you can handle keeping your Threads clean. If you can keep the ThreadLocal namespace clean and you can ensure your run() methods come to a clean end, then there is probably no need to do anything on the Executor - the Thread is free to be re-used if that is how the Executor is configured. On the other hand, there is a school of thought saying you shouldn't be so sure you can keep all the problems associated with an exception localized. If the exception occurs it could have side effects in multiple threads and could cause a cascade of problems. So you would be safe to shut it all down, kill the entire Executor and all threads in it, then restart all the Threads which were running (ensuring a fresh clean state). I think this is probably overkill in your case as long as you don't have a lot of shared state between threads and can keep things clean and isolated as described above.

Steve
Nate Lockwood
Ranch Hand

Joined: Feb 22, 2010
Posts: 83
Thanks, and thanks for the references, too. I've got some reading and thinking to do!

Nate
 
 
subject: stopping a thread (runable)