Not leaving a method until a Thread has finished

J

james

Hi,

I have a method where a Thread needs to complete a task independently
of another task outside my Thread on the main Event Dispatching Thread.
However, I don't want to leave the method goTask() until the Thread t
completes.

I am not sure if this is possible without blocking the Event
Dispatching Thread and if it is possible please can someone help me.

The test program below demonstrates my problem (I hope) with the use of
System.out's.

Essentially, I don't want to get to the:

System.out.println("I don't want to get here until the thread t has
finished.");

before:

System.out.println("About to finish Thread");

has been output.

I hope this makes sense and someone can assist me here.

Thank you,

James

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;

public class Sync extends JFrame{

/* Swing components */
protected JPanel contentPane;

public static void main(String[] args) {
try{

UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
Sync s = new Sync();
s.setVisible(true);
}
catch(Exception e){
e.printStackTrace();
}
}

public Sync(){
Dimension dimension = Toolkit.getDefaultToolkit().getScreenSize();
jbInit();
this.setSize(new Dimension(100,100));
Dimension frameSize = this.getSize();
this.validate();
this.setLocation((dimension.width - frameSize.width) / 2, 0);
}

public void jbInit(){
contentPane = (JPanel) this.getContentPane();
contentPane.setLayout(new BorderLayout());
this.setTitle("Simple Test");

JButton jb = new JButton("Go Task");
jb.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
goTask();

System.out.println("I don't want to get here until the thread t
has finished.");
}
});
this.contentPane.add(jb, BorderLayout.CENTER);
}

public void goTask(){

Thread t = new Thread(new Runnable() {

public void run() {
for(int i=0;i<10;i++){
try{
Thread.sleep(500);
}catch(Exception e){
e.printStackTrace();
}
}
System.out.println("About to finish Thread");
}
});
t.start();

System.out.println("This needs to be done seperatly to the
thread.");


}
}
 
I

Ingo R. Homann

Hi,

Hi,

I have a method where a Thread needs to complete a task independently
of another task outside my Thread on the main Event Dispatching Thread.
However, I don't want to leave the method goTask() until the Thread t
completes.
t.join();

I am not sure if this is possible without blocking the Event
Dispatching Thread and if it is possible please can someone help me.

Ehh, not sure if I understand you right, but: You cannot block without
blocking! ;-/

So...
public void actionPerformed(ActionEvent arg0) {
goTask();

System.out.println("I don't want to get here until the thread t
has finished.");
}
});

....perhaps, it's a good idea to start a new Thread here:

public void actionPerformed(ActionEvent arg0) {
new Thread(){
public void run() {
goTask();

System.out.println("I don't want to get here until the thread t
has finished.");
}
}
}.start();
}

Hth,
Ingo
 
J

james

Ehh, not sure if I understand you right, but: You cannot block without
blocking! ;-/

Sorry, essentially I mean I want to stop at the end of my goTask()
method but I want the Event Dispatching Thread to still be able to
update the GUI.
...perhaps, it's a good idea to start a new Thread here:

The code I posted was a simple example of my situation in order to
demonstrate the issue I was having. Unfortunatly, I can't adopt the
solution you suggested.

I will look in to the t.join() to see if it will help me.

Any further advide is appreciated.

James
 
T

Thomas Weidenfeller

I have a method where a Thread needs to complete a task independently
of another task outside my Thread on the main Event Dispatching Thread.

About how many threads are we talking?

A) EDT, task-1 thread, task-2 thread, or

B) EDT, task-2 thread?

If A), I don't see your problem at all. You have two task threads
independent of the EDT, and want to synchronize them: join()

If B), you can't wait for the task thread to die (join) from within the
EDT. You also can't wait for the EDT to die - it should never die, but
if it does, your application is in real trouble.

Ok, you can join, but your GUI will freeze. No screaming and kicking
will change this. You either play by the rules, or your GUI will freeze.
All these "but I don't want to" will not help your. See Q3.1, Q3.2, Q4.2
of the comp.lang.java.gui faq, and Sun's GUI tutorial.

/Thomas
 
I

Ingo R. Homann

Hi,

Sorry, essentially I mean I want to:
(1) stop at the end of my goTask() method
(2) but I want the Event Dispatching Thread to still be able to
update the GUI....
(3) Unfortunatly, I can't adopt the solution you suggested. (start
another Thread)

The specification of your problem is corrupt: (1), (2) and (3) are a
contradiction - you must drop one of these requirements!

Ciao,
Ingo
 
J

james

Thanks for the help. I will have to look in to A) with the join() that
should hopefully sort my problem.

Will update the topic with how i get on.
 
E

Esmond Pitt

Thanks for the help. I will have to look in to A) with the join() that
should hopefully sort my problem.

The join() won't solve your problem, it will block the event dispatching
thread. What you really want is a completion callback.
 
J

james

I have just discovered that join is blocking the EDT. I will look in to
the completion callback that you mention now.

If you have any sample code of reference pages I would be grateful.

James
 
I

Ingo R. Homann

Hi james,

I have just discovered that join is blocking the EDT.

Arg, join() does *not* especially block the EDT! It blocks the Thread
that calls it.

What you want is calling it from the EDT without blocking the EDT, which
is like (as we say in germany) "Wash me but I don't want to become wet."

Everything you complain about is not a lack of Java or Threads or the
EDT or join(), its a lack of your wishes!
I will look in to
the completion callback that you mention now.

If you have any sample code of reference pages I would be grateful.

I mentioned that before, at the beginning of this thread:

public void actionPerformed(ActionEvent arg0) {
new Thread(){
public void run() {
goTask();
t.join();
doSomethingElse();
}
}.start();
}

Ciao,
Ingo
 
R

Rogan Dawes

Hi,

I have a method where a Thread needs to complete a task independently
of another task outside my Thread on the main Event Dispatching Thread.
However, I don't want to leave the method goTask() until the Thread t
completes.

I am not sure if this is possible without blocking the Event
Dispatching Thread and if it is possible please can someone help me.

The test program below demonstrates my problem (I hope) with the use of
System.out's.

Essentially, I don't want to get to the:

System.out.println("I don't want to get here until the thread t has
finished.");

before:

System.out.println("About to finish Thread");

has been output.

I hope this makes sense and someone can assist me here.

Thank you,

James

It sounds to me like you want to use something like the SwingWorker
class posted by Sun. Google for SwingWorker, and you should find it, and
a tutorial explaining how to use it.

<http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html>

Alternatively, consider FoxTrot, which is an alternative implementation
of a similar concept. <http://foxtrot.sourceforge.net/>. The creators
think that it is a cleaner way of writing your logic . . .

Good luck.

Rogan
 
J

james

For peoples reference I solved this issue issue using FoxTrot avaliable
from http://sourceforge.net/.

I heard about this from this very useful presentation on
Threads/SwingWorker:

http://javalobby.com/eps/galbraith-swing-2/

Even though not mentioned above (for simplicity sake) the issue I was
trying to solve was with regard to displaying a Progress Bar that would
update with respect to the progress of another task. I implemented a
number of the Java examples without issue however when extending them
to my application I was having a great deal of trouble getting the
Progress Bar to display before the task completed.

I hope people find this topic of some use.

Thanks to everyone who helped.

James
 
J

james

Thanks Rogan,

I eventually found out about FoxTrot this morning and it was exactly
what I was looking for.

James
 
S

steve

Thanks Rogan,

I eventually found out about FoxTrot this morning and it was exactly
what I was looking for.

James

you might want to give it a miss considering the project is only released
every couple of years.
 
R

Rogan Dawes

steve said:
you might want to give it a miss considering the project is only released
every couple of years.

Why is that a bad thing? If the tool works, and has no bugs, why should
they make any changes to it?

It is a simple concept, presumably well-executed. Once it is finished,
what more needs to be done? Why should there be any more releases?

Rogan
 
T

Thomas Weidenfeller

Rogan said:
Why is that a bad thing? If the tool works, and has no bugs, why should
they make any changes to it?

I don't know steve's reasons, mine are:

It is a hack. It might break any time if Sun does some minor update to
some of the interfaces FoxTrot use. As soon as the release cycle of the
tool is slower than Sun's JDK/JRE release cycle you get locked into a
particular release or have to count on your luck. You get the source
code, so you can fix minor things, but if Sun locks the used back doors
for good (accidentally or not), you are done. Then you have to
re-structure your whole application if you want or need to upgrade to a
newer Java version.

It is also risky with respect to non-Sun Java implementations. Is there
a guarantee that these implementations will always show the same
behavior on which FoxTrot builds?

I also have a general problem with FoxTrot. It doesn't add value. Why do
people want to replace thread handling with, yes, you guessed it, a
thread? FoxTrot can't do more than these few lines of code:

new Thread(new Runnable() {
public void run() {

// run the time-consuming task
...

// update the GUI from the time-consuming task
SwingUtilities.invokeLater(new Runnable() {
public void run() {

// GUI update stuff

}
});

}
}).start();


I don't know why people fear this code. Yes, there is a real Thread
involved. Uhhh. And two Runnables(). So what? If this is already to
complicated, then I don't want to see the rest of the application.

It is sad that the OP ignored all the good advice he got about getting
the threading right. FoxTrot is really not a solution.

/Thomas
 
A

Andrea Desole

Ingo said:
The specification of your problem is corrupt: (1), (2) and (3) are a
contradiction - you must drop one of these requirements!

I think Ingo is kind of right. Something in the requirements doesn't
match. Basically, you can't wait for a thread (which implies a
synchronous operation) doing other things (which implies an asynchronous
operation).
What you probably want is a notification. That is, you want your main
thread to be notified when goTask is done. So you can implement an extra
method in your Sync class, something like:

public void done()
{
System.out.println("I don't want to get here until the thread t
has finished.");
}

then pass the class Sync to your thread, and let the thread call done()
when it's about to exit. Of course, you have to watch all the
synchronization issues.
Just an idea

HTH
 
J

james

I do not feel it is fair for you to say it is sad. The code I posted
was an extremely simplistic view of of the problem I was having which
was looked at by 4 Java programmers with about 20 years experiance
between them.

I spent 2 days playing around with the various suggesstions people made
none of which solved my issue. I could not use the solution you
presented above as the time consuming task had to execute seperatly
and the GUI had to update at regular intervals based upon this task.

I also could not leave the method in which the time consuming task was
started until it finished. However, if I used join I was blocking the
EDT and no GUI updates occured.

I am sure there is another solution but I failed to find one which met
my needs. I have implemented the solution using FoxTrot and it works
perfectly. If Sun make any changes which FoxTrot do not do an update
for then yes I agree there would be an issue and at that time I will
have to look back at the solution and find another way. Perhaps, Java
will have added some additional features which will help me implement a
different solution.

I appreciate all the comments people have made and hoep this topic
helps some other people.

I did not ignore any of the advice posted and was grateful for all the
suggestions and in my case FoxTrot was a solution and was a solution I
have found a lot of reference to on the web.

Thanks again.

James
 
I

Ingo R. Homann

Hi,

I spent 2 days playing around with the various suggesstions people made
none of which solved my issue. I could not use the solution you
presented above as the time consuming task had to execute seperatly
and the GUI had to update at regular intervals based upon this task.

I also could not leave the method in which the time consuming task was
started until it finished. However, if I used join I was blocking the
EDT and no GUI updates occured.

I am sure there is another solution but I failed to find one which met
my needs. I have implemented the solution using FoxTrot and it works
perfectly.

The point is: Although I have never heard something about FoxTrot I'm
sure that it solves the problem in a way very similar to the solutions
Thomas and I presented, because there *is* no other kind of solution
(especially for your mis-defined problem).

I don't know why to use a tool like FoxTrot so solve a problem that can
be solved in 5 lines of code.

Ciao,
Ingo
 
J

james

I tried the code in Thomas's post with no sucess. I am sure it may work
in most situations but in the rather complex set up I am tying to
implement it did not work as required.

Thanks anyway.
 
T

Thomas Weidenfeller

Ingo said:
The point is: Although I have never heard something about FoxTrot I'm
sure that it solves the problem in a way very similar to the solutions
Thomas and I presented, because there *is* no other kind of solution
(especially for your mis-defined problem).

Well, FoxTrot does some heavy-lifting: It manipulates the event pump
(like it is done for modal dialogs) via some interfaces which Sun most
likely accidentally left open. Basically, it moves the event pumping
temporarily to another new thread and lets you abuse the EDT for some
time-consuming task in the meantime.

Compared to the suggested normal solutions - which the OP is unwilling
or unable to comprehend - FoxTrot switches the roles of the threads,
giving users the "cozy" feeling of not having to leave the beloved EDT
for some time-consuming work. I don't consider that a major breakthrough.
I don't know why to use a tool like FoxTrot so solve a problem that can
be solved in 5 lines of code.

That's what people try to tell the OP for days now. I have chalked it up
as a lost cause. If he wants to mess up his code, he should do it.

/Thomas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,007
Latest member
obedient dusk

Latest Threads

Top