How to monitor Threads

Hi,

I have an application that does a series of tests. Each test has its own class. When an user selects a test from a combo box the test is executed. Within the class I have a thread running because the I am waiting for a response from a microcontroller.

My next task is to make an automated test so when the user presses the button the tests are executed sequentially. Here is my problem:

I need to start test1 and then test2 and then test 3...etc only when a test has completed.

This the code used when a user presses the button:

publicvoid actionPerformed(ActionEvent e){

TestPanel testPanel = (TestPanel)projectTree.getTestPanel();// Getting the test panel object from the projectTree

int testSelected = testPanel.getTestSelected();// Getting the test selected by the tester

switch(testSelected){

case 0:

new FullPowerMode(testResultsPanel).start();

break;

case 1:

new MediumPowerMode(testResultsPanel).start();

break;

case 2:

new LowPowerMode(testResultsPanel);

break;

case 3:

new LowBatteryCheck(testResultsPanel);

break;

...

}

}

For the automated button I have the following code

privatevoid autoTestBtActionPerformed(java.awt.event.ActionEvent evt){//GEN-FIRST:event_autoTestBtActionPerformed

final FullPowerMode fullPower =new FullPowerMode(testResultsPanel);

final MediumPowerMode mediumPower =new MediumPowerMode(testResultsPanel);

final LowPowerMode lowPower =new LowPowerMode(testResultsPanel);

autoStep = 0;

autoTimer =new Timer(1000,new ActionListener(){

publicvoid actionPerformed(ActionEvent e){

switch(autoStep){

case 0:// Start the fisrts test

fullPower.start();

autoStep = 1;

break;

case 1:

if(!fullPower.isAlive()){

System.out.println("Thread: " + fullPower.isAlive() +"\nTimer: " + fullPower.isTimerRunning());

mediumPower.start();

autoStep = 2;

System.out.println("Starting mediumPower");

}

break;

case 2:

if(!mediumPower.isAlive()){

System.out.println("Thread: " + mediumPower.isAlive() +"\nTimer: " + mediumPower.isTimerRunning());

lowPower.start();

autoStep = 3;

}

break;

case 3:

if(!lowPower.isAlive()){

autoStep = 4;

}

break;

case 4:

break;

}

}

});

autoTimer.start();

}//GEN-LAST:event_

The problem im facing is that I dont know when the thread has stoped running in order to start the next test.

How could I achieve this is there another way?

Best Regards,

Nick

[4865 byte] By [nk15a] at [2007-10-2 21:49:25]
# 1

You can use a (static) variable as monitor. In every thread it could look like this

static Object synchronizationObject = new Object()

and in the run/start function of the Threads

while(synchronizationObject!=this){

if(synchronizationObject==null)

synchronized(getClass()){

if(synchronizationObject==null)

synchronizationObject=this

}

}

else

synchronized(synchronizationObject){

try{

synchronizationObject.wait()

}catch(Exception e){}

}

}

and at the end of your run

synchronized(synchronizationObject){

synchronizationObject.notifyAll();

}

synchronizationObject=null;

With this you should be able to queue your threads up, but the order can't be fixed set with this.

When you need a specified order of your thread, you should put them into an ArrayList/Vector and start them in your list with join() or you start with "run()" (without join()), but then you could also use normal functions ;-)

Message was edited by:

Jungi-X

Jungi-Xa at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 2
Hi,I was just looking at this in the Thread tutorial. Thanks a lot I will try out :)
nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 3
Hi,I tried this but it seems that nothing is running now.I added it in the run() method. In the run() method I have code that prompts a dialog box but it doest show now.Any suggestions?
nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 4
Simply use the Thread.join()-method, e.g.fullPower.start();fullPower.join();mediumPower.start();mediumPower.join();// ...
falke2203a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 5
HI,I tried what you suggested but the hole program now freezes.
nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 6
my fault ^^;at the end of the run() method you must also set the synchronizationObject to null, otherwise it will sleep til the end of time. sorry 'bout that.
Jungi-Xa at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 7

Still no luck. When I use join() it all freezes.

Here is part of a class:

public class FullPowerMode extends Thread{

static Object synchronizationObject = new Object();

// Other variable declarations

public FullPowerMode(TestResultsPanel testResults){

this.testResults = tesResults

comms = Comms.getInstance();

sendFullPowerCmd();

}

public void run(){

while(synchronizationObject!=this){

if(synchronizationObject==null)

synchronized(getClass()){

if(synchronizationObject==null)

synchronizationObject=this

}

}

else

synchronized(synchronizationObject){

try{

synchronizationObject.wait()

}catch(Exception e){}

}

}

/* My code goes here */

synchronized(synchronizationObject){

synchronizationObject.notifyAll();

}

synchronizationObject=null;

}

}

nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 8

When using join(), you do not need the monitor (those synchronized blocks) anymore. The deal with join is that you tell the calling thread to wait until the callee thread is died.

In the run()-methods of your threads themselves you don't need to care about execution order in this case. Just process the data as needed (in your last example, only the part denoted with /* My code goes here */ is needed).

In the calling thread (which shouldn't be the main thread to avoid freezing and to let you keep control) you just call t.start(); and t.join(); for every thread/test you want to execute.

falke2203a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 9

Maybe i was not clear. Your synchronizationObject should be in a class which all of your threads can reach. (maybe your main application). If it still don't work, please give information where it stops working (use debug output, breakpoints etc. to analyse) or use "join()" (then without synchronization object)

Jungi-Xa at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 10

Ok I removed all the sync code and added the join(). It doesnt seem to get stuck anymore. The thing is that it will not do what I want. In other test classes I have a timer running that checks for any reponses and according to a response a dialog might be displayed. I dont know how long this process will take as it varies.

A thread is dead when the run() is executed. For example:

1. Test 1 starts

2. SendCommand to microcontroller

3. Start Timer

4. In public void actionPerformed(ActionEvent e) check for any responses

5. Stop Timer if a response has been received else wait for a response and timeout if nothing has been received

6. Start Test 2 if and only if Test1 has completed.

Now the thing is how do I control this and only start Test 2 when Test 1 has been comleted?

Should I just use a flag in the class that I should check to see if the test has been completed?

I appreciate your help very much.

Thanks

Message was edited by:

nk15

nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 11
I traced why the program got stuck. Apparently AWT-EventQueue-0 thread is waiting (Button click to start the test). This only happens when I put the thread to sleep (FullPowerMode) and use join().Message was edited by: nk15
nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 12

OK I tried out some things in order to understand whats going on. In the run() I added:

public void run(){

while( count != 0 ){

try{

System.out.println("In thread");

count--;

sleep(1000);

}catch(InterruptedException e){}

}

And when calling the thread:

fullPower.start();

fullPower.join();

This will freeze everything until the while condition isnt true. This wasnt clear to me. But how can I make this run in the background and not freeze the hole application? Should I use implements Runnable?

nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 13
As I said in my last post - start those threads from a different thread than the main thread, for example you could use SwingUtilities.invokeLater() (see http://java.sun.com/j2se/1.5.0/docs/api/javax/swing/SwingUtilities.html#invokeLater(java.lang.Runnable))
falke2203a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 14

I did the following but it still gets stuck:

private void autoTestBtActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_autoTestBtActionPerformed

final FullPowerMode fullPower = new FullPowerMode(testResultsPanel);

final MediumPowerMode mediumPower = new MediumPowerMode(testResultsPanel);

Runnable doTests = new Runnable(){

public void run(){

fullPower.start();

try {

fullPower.join(2000);// Timeout

} catch (InterruptedException ex) {

ex.printStackTrace();

}

mediumPower.start();

try {

mediumPower.join(1500);

} catch (InterruptedException ex) {

ex.printStackTrace();

}

}

};

SwingUtilities.invokeLater(doTests);

}//GEN-LAST:event_autoTestBtActionPerformed

Is this what you mean?

Regards,

Nick

nk15a at 2007-7-14 1:05:10 > top of Java-index,Desktop,Developing for the Desktop...
# 15

Exactly. But unfortunately you didn't provide any information how it gets stuck. During development it is often helpful to add some System.out.println()s with debug information, being able to trace the program flow without having to use a debugger.

Add those outputs and see where exactly your program hangs. Possible locations are before/after invokeLater(), before/after <ThreadX>.start() and join(), within the different run methods at relevant locations and so on.

Special hint: Instead of System.out.println() you could use a logging mechanism, like Log4J or the Java-own one (search doc for Logger). This way you you can get more detailed information (e.g. including thread/method information) and usually needn't clean the code before going productive (changing the output level works in most cases).

falke2203a at 2007-7-21 8:08:45 > top of Java-index,Desktop,Developing for the Desktop...
# 16

Hi,

When I mean it gets stuck I mean that the UI doesnt respond for the duration of the running thread. I read that join() causes it to wait there until the thread is dead so the EDT thread is also waiting as a result freezing the UI for a while.

But the invokeLater shouldnt release the Event?

nk15a at 2007-7-21 8:08:45 > top of Java-index,Desktop,Developing for the Desktop...
# 17
Ok, this was my fault... I should have read the api doc myself before giving advises...Instead of SwingUtilities.invokeLater(Runnable) you should be able to solve your problem with new Thread(Runnable).start();Hope this time my tip is a bit more helpful :/
falke2203a at 2007-7-21 8:08:45 > top of Java-index,Desktop,Developing for the Desktop...
# 18
Hi, Its Ok I created a new Thread in the ActionEvent and do all the tests in there. This seems to be working OK now and releases the Event Queue.Thanks for yout time.Regards,Nick
nk15a at 2007-7-21 8:08:45 > top of Java-index,Desktop,Developing for the Desktop...