Link to home
Create AccountLog in
Avatar of dpalyca755
dpalyca755

asked on

notification/detecting thread failure in main

How in the main{ }of my application can I be notified that a worker thread has exited/stopped?
The worker threads are designed to run continuously unless a critical error occurs.
If it does, the main needs to know they stopped or exited to then act on it.

main {

//create runnable worker "classA"
start classA in it's own thread

...Handle the thread stopping condition

}
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

It could be as simple as calling a method in a controlling class from the catch block
You mention handling failure, however later you are asking about dealing with a stop condition, and the two things are obviously different.

But you can see what happens when a thread stops naturally in this code :

import java.util.*;

  class Joiner extends Thread{
    
   private boolean _bEnter;
    private int single=0;
    private static int nThrds = 0;
    static int oldactivecount=0;
     
   static ThreadGroup tg = new ThreadGroup("tg");
   
     public Joiner(ThreadGroup t, String name){super(t,name);}

	public void run(){

		single = tg.activeCount();

		System.out.println("Thread "+this.getName()+" started "+new Date()+" ");

		if(tg.activeCount()==1){System.out.println("Single thread.");enter();exit();System.exit(0);}
		
		enter();
		
		synchronized(tg){System.out.println(this.toString()+" is waiting\n");try{tg.notify();tg.wait();}catch(Exception f){}}
		
		exit();

		tg.list();//System.out.println("\n");

		if(tg.activeCount()<=2){synchronized(tg){tg.notifyAll();}}
		
	}

	public static void main(String[] args){

		final int NUMTHREADS = new Integer(args[0]).intValue();
		nThrds = (Integer.parseInt(args[0]));
		Thread t;
		oldactivecount=nThrds;
		t = new Thread(new Runnable(){public void run(){while(true){if(oldactivecount>tg.activeCount()){System.out.println("Lost a thread again. Please deal");oldactivecount=tg.activeCount();}}}});
		t.setDaemon(true);
		t.start();
		for(int y=0;y<NUMTHREADS;y++){(new Joiner(tg,Integer.toString(y))).start();}		

		
	}


                public  void enter() {

			//_bEnter = true;
			
			try{Thread.sleep(1000*(Integer.parseInt(this.getName()))); }catch(InterruptedException i){}
			}


	public   void exit(){
	
			
			
    			 //_bEnter = false;
			
			if(activeCount() ==1){System.out.println("Last thread, now in exit() . . ." );System.out.println("Thread "+this.getName()+" ended "+new Date()+"\n");System.exit(0);}
			
			try{Thread.sleep(1000*(Integer.parseInt(this.getName()))); }catch(InterruptedException i){} 
			System.out.println("Thread "+this.getName()+" ended "+new Date()+"\n");					
			    
	}
    
   }

Open in new window


In the overly long and badly laid out line 40, you would be able to handle the fact that a thread has terminated somewhere here as an example.

(Input the number of threads you want to run as the argument to main())
It would be best to keep your distance from the sort of code I gave above, as it's not really OOP friendly. In the real world, handling an exception as CEHJ has hinted at, is preferable.
Avatar of dpalyca755
dpalyca755

ASKER

CEHJ,

When you say as simple as catching a the condition/error in the class running in the thread and calling a method in the controlling class, can you provide an example?
Is my crude example below what you mean for the main controlling class?
In the example below I would have ClassA's exception handling call MyMainClass.processWorkerThreadFailure();

If a subthread calls a method in the main class, does it imply the subthread dies once the runnable class exits?
Part of my error handling, in the processWorkerThreadFailure method,
will be to do some cleanup, but then restart runnable Class A & B.
Please advise.

MyMainClass{

MyMainClass(){
}
Main () {
Instantiate runnable ClassA
Instantiate runnable ClassB
New Thread (ClassA).start();
New Thread(ClassB).start();
}

public static void ProcessWorkerThreadFailure () {
//handle issue
}

} // End MyMainClass

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
CEHJ,

I like this option, but quick question..
Is this not considered a circular dependency?
or if it is, is am acceptable one?
Please advise?

Thanks
Yes, it is. That's a good point. A better way would be either to implement Observer/Observable or define a custom event and raise the event to any registered listeners. For a class that's unlikely to appear in another context (IF it's such a class) that could be overkill
How about using ExecutorServices with callables instead of runnables?  I could throw the exceptions up to the main that way and then take action uniquely based on the error.
Yes, but that's not any different to what's already been suggested. How the thread is produced and in what wrapper is not really relevant
:)