Win a copy of Murach's Python Programming this week in the Jython/Python forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

Communication between threads  RSS feed

 
Kaush Kane
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hello,
I am designing a thread based application where the Main thread is spawning 3 different threads. In the main thread I am waiting for each thread to finish using the "join()" method.

I need to enhance this logic so that if any of the three threads fail then it should be reported to the Main thread and then Main thread should kill the remaining two threads.

How can I achieve this? How can my Main thread know which thread has failed and which two threads to kill. Please find my sample code below:


/* This is my Main thread */
ToolThread[] runThread = new ToolThread[3]
for (int i = 0; i < 3; i++) {
runThread[i] = new ToolThread(i);
runThread[i].start();
}

for (int j = 0;j<3;j++) {
try {
runThread[i].join();
}
catch (InterruptedException ex) {
}
}



Please let me know.

Regards,
Kaustubh Kane.
 
Nicholas Jordan
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I went through the grinder on this, and developed a good grasp of what you are trying to do. Simple and short answer is to make a boolean or two or possibly a, hang on folks, runlevel (integer) then sample it from the main thread or whatever controller thread needs to have information about the worker threads.

Due to what is usually reserved to compiler science, I suggest you make these communication variable volatile - it is an involved discussion and I suggest you rely on testing and your idea of how the program is supposed to run to make decisions about the use of the keyword volatile. I found that an earler work, written in C/C++ was sluggish on kill command until I figured out to make the paramater in the constructor volatile.

this is what I did:



I only ran one test session and that was sufficient to tell me I could go on to other design phases of prototyping - which I am deep in but the people that helped me with this will be watching and can provide effective assistance, but join() blocks as I recall from their advice and to do what you are attempting to code requires what is called a busy loop. I suggest Java Threads by Scott Oaks and Henry Wong. There are many issues besides join that you will have to address and the book is remarkably understandable.

Be advised, threaded programs on a single processor machine will run in a manner that is difficult for the first-time student to grasp. It is just the way machinery works and is a consequence of some computer design issues that are buried in real-world design issues.
[ August 22, 2007: Message edited by: Nicholas Jordan ]
 
Nitesh Kant
Bartender
Posts: 1638
IntelliJ IDE Java MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There is no way that you can kill a thread in java. As the stop() and suspend() methods are deprecated.
The only good you can do is to ignore their results.
How do you determine that one of your threads have failed?
If you are on jdk5, try using Futures, it will be useful.
 
Edward Harned
Ranch Hand
Posts: 291
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There isn't enough room here to describe how to do what you want. Very briefly:

You'll need to pass a common Object to each new thread. The Object should contain information about each thread such as its identifier, whether its finished normally or wants to cancel, etc.

Forget join(). Use java.util.concurrent.CountDownLatch. As each thread completes, it updates its entry in the common Object and counts down. If a thread wants to cancel, it so marks the common Object and forces the latch count to zero ( for (; latch.getCount() > 0; latch.countDown()){})
 
Kaush Kane
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot for all your suggestions. I am planning to use the CountDownLatch.

Following is the sample code. Could you please do a quick review and give your comments:

/* This is my Main thread */
CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(3);

ToolThread[] runThread = new ToolThread[3]
for (int i = 0; i < 3; i++) {
runThread[i] = new ToolThread(i);
runThread[i].start();
startSignal.countDown(); // let all threads proceed
int return = runThread[i].getStatus();
if (return != 0) {//this means error
// forcing the latch count to zero
for (; doneSignal.getCount() > 0; doneSignal.countDown()){}
}
doneSignal.await(); // wait for all to finish

}



class ToolThread extends Thread {
private final CountDownLatch startSignal;
private final CountDownLatch doneSignal;
private int status;

ToolThread(CountDownLatch startSignal, CountDownLatch doneSignal) {
this.startSignal = startSignal;
this.doneSignal = doneSignal;
}

public int getStatus(){
return status;
}
public void run() {
try {
startSignal.await();
status = doWork();
doneSignal.countDown();
}
catch (InterruptedException ex) {}
}

}
 
Edward Harned
Ranch Hand
Posts: 291
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Not even in the ball park.
 
Kaush Kane
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi edward,
Could you please give me more info.
 
Kaush Kane
Ranch Hand
Posts: 37
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi Edward,
Ok. Got your point. My implementation had issues.
But I have one doubt though.

Say I have three threads. My first thread failed and hence it forces the latch count to zero. This will make sure that my Main thread does not wait for the remaining threads.

But here the issue is the remaining threads would still continue to run. Requirement is that i need to kill remaining threads if one of the thread fails.

Please let me know.
 
Yuriy Zilbergleyt
Ranch Hand
Posts: 429
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Personally I'd keep the joins and have the child thread encountering an error set it's threadId into the main thread and then interrupt it. When the main thread catches the interrupted exception, it checks the threadId set by child and knows which threads it needs to kill. Then the main thread can set a boolean value in the child threads that they will check periodically. If the child threads are waiting on some input themselves, the main thread can interrupt them.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In general the preferred way to cancel a task in Java would be as Yuriy said, call interrupt() on the thread that you want to stop. However, this assumes that the thread has been written in a way that can be interrupted. If the thread uses methods which are declared with "throws InterruptedException" then chances are good that it's already interruptible. Otherwise you may need to insert some periodic checks like

You also need to be careful where you put your catch blocks. Chances are, you want many of your methods to not catch InterruptedException at all. Let it be thrown out of each method. Except for the run() method, where you finally catch it just before exiting the method.

If the other code you need to invoke is not interruptible and you can't modify it, then you have problems. Java doesn't really have any good mechanism to end a thread under this circumstance. See Why are Thread.stop, Thread.suspend and Thread.resume Deprecated? for more info. If you're desperate, you could try calling Thread's stop() method. It might work. And maybe it won't break anything important. Maybe.

One other alternative is to not use threads at all, but instead use processes. You can use Runtime.getRuntime().exec() (or since JDK 5, ProcessBuilder) to spawn a new Process for each task. Then if a Process is taking too long, use destroy() to kill it. This will probably take somewhat more overhead than Threads would. And it's more difficult to communicate between processes than threads - you can't just pass objects in and out of processes; you need to use streams. But if your requirement about being able to cancel a task is important enough, maybe this is a way to do it. Good luck.
 
Edward Harned
Ranch Hand
Posts: 291
Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Research.
Analysis.
Design.
Coding.

You're missing the first three. In order for threads to talk to each other they need some common storage (Java Class) shared between them. As I first said, there isn't room here to put it all.

What does the main thread need to share with the started threads? What does each started thread need to share with the main thread? What does each thread need to share with the other started threads? Then develop a Class that contains this information and pass it to the constructor of each new thread. Hint: CountDownLatch belongs there as does CyclicBarrier.

Once you have the fields, then move on to the methods. Coding is at the bottom of the list.
 
Bob Ruth
Ranch Hand
Posts: 320
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perhaps you could find a way to use Thread's isAlive() method from the main thread.

A child thread, depending on how it dies, may not always be able to send an interrupt back to the main thread.

Perhaps put your spawned Thread objects in an ArrayList and periodically iterate through it checking for dead ones using isAlive(). If you find a dead thread, remove it from the collection. When you have finished the pass through the collection doing the weeding of dead threads, call another method that iterates through the collection sending interrupts to each remaining threads.

As others have said, each thread must be able to detect and catch the type of interrupt that you will be sending from the main thread and use that to close themselves down.

If you want actual intelligence to be collected about the nature of the thread death, then you will have to handle exceptions under the threads and report them individually, or develop a means of passing a "death certificate" back to the main thread for processing.

Bear in mind, this dramatically over-simplifies dealing with these matters....there is certainly some research to do. But the concept may be of some help to you.

------------------------------------------------------

Just poking through the 5.0 API .... something else you might want to look at is the set/getDefaultUncaughtExceptionHandler(). I have not researched it but, just from reading it's description, it might be a way to define a common handling routine for the "unable to send an intterrupt" type of abrupt thread death.

You might also be able to use Thread's getStackTrace() method to get/display the stackTrace from a dead thread. Again, I have not researched it.... just saw it in the API.

Thread's getState() might be useful to instead of isAlive(). It actually tells the state of the thread....
[ August 24, 2007: Message edited by: Bob Ruth ]
 
Nicholas Jordan
Ranch Hand
Posts: 1282
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

[Nitesh Kant:]There is no way that you can kill a thread in java. As the stop() and suspend() methods are deprecated.

I disagree.

[dward Harned:]There isn't enough room here to describe how to do what you want.

Very briefly, imagine the energizer bunny on fresh batteries, it's 4am on the bonneville salt flats. Assuming no races scheduled for the next month or so andignoring salt corrosion of toy bunnies, how many kilobunnies per hectacre would you suggest ?

[Kaush Kane:]My implementation had issues.
Can you provide us a handle on the problem domain ?

[Kaush Kane:]Main thread know which thread has failed and which two threads to kill.

Though not immediately apparent from your question, the only reason the main() thread would need to know is if there is some cleanup or error code that needs to exec in the other two objects. It's a little funny to grasp, but just because the code has run() ... does *not* mean that the instance has gone out of scope. For example, removing entries from a collection could be done by setting named variables to null. This does not mean that you set a Thread instance EnhanceLogic[] enhance = new EnhanceLogic[4]; in my code, to null -- it means in the code, where you have a varable that is instantiated with the new operator, you can still access the variables of that instance,....  even though the code has completed running.  

Note: you would add some OO stuff, just make it synchronized, to access the started / isFinished / isWorking type of variables from other parts of the program that may be running under different Threads, but steadfastly resist the impulse to make sequences make sense ~ the machine's page demand algorithm in tandem with single-processor machines makes a mish-mash of human thought.

[Yuriy Zilbergleyt:] If the child threads are waiting on some input themselves

Don't let them be waiting on System.in - it blocks: Windows, I/O is not interruptable.

[Jim Yingst: general the preferred way to cancel a task in Java would be as Yuriy said, call interrupt() on the thread that you want to stop. However, this assumes that the thread has been written in a way that can be interrupted. If the thread uses methods which are declared with "throws InterruptedException" then chances are good that it's already interruptible. Otherwise you may need to insert some periodic checks like ....

I feel these should be done with member variables, so that programming by throwing exceptions is reserved to exceptional conditions that fit the mental model suggested by the word exception. I tried making the int[] volatile and got some compiler errors in the instance constructor. I was able to get a clean build an posted what I had for discussion, but it is futile to do deep-cycle testing until O.P. tells us design objectives.

I was discussing this with Jack, a trained industrial engineer and team member, and blurted the words: except if the exception is an exceptional exception , which is ususally futile in the general case. Special cases are explored routinely in Meaningless Drivel.

[Edward Harned:]*(Original Poster) missing the first three.
I found that it was much easier to code my entire project, then back-up to some of the overall analysis thought tools that many suggest. This eliminated trying to figure out what the code is supposed to do without having any code that is supposed to be doing something. What I came up with is much more sophisticated than what I wrote for O.P., it is the passing of information from one part of the program to another that should be immediately solvable by the advanced schools.

If that is so, why is public final native boolean isAlive(); not synchronized ? I doubt that even Horstmann gives a good, in depth workup of Threading, but it seems so obvious to me that it is just a matter of mechanically inclined working in the same group as those who download ringtones and eat low-carb food.
[ August 27, 2007: Message edited by: Nicholas Jordan ]
 
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!