Thread stuck in state NEW?

M

Mark Space

Hi all, I was planning on doing some swing testing, but ran into a
thread issue instead. The problem is a small anonymous thread class I
create stays stuck in state NEW, even though it apparently runs an
completes.

package crazythreads;

import javax.swing.JOptionPane;

public class Main
{
public static void main(String[] args)
{
Main test = new Main();
System.out.println( test.thready() );
}

private String thready()
{
String result = null;
Thread t = new Thread(){
public void run() {
//result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null,"Enter a random string:");
}
};
javax.swing.SwingUtilities.invokeLater(t);
try {
while( t.getState() == Thread.State.NEW ) // STUCK HERE
Thread.sleep(100);
while( t.getState() != Thread.State.TERMINATED)
t.join(100);
} catch( Exception ex) {ex.printStackTrace();}
if( result == null )
return "No result.";
return result;
}
}

The debugger shows the main thread stepping through the while loop at
the comment STUCK HERE. The Thread, t, does run: I see it's dialog box
come up, I enter a value and press OK. So it should at some point be in
one of the running states (probably blocked on IO). Before adding the
while loops, the main thread did not wait (at the t.join()) and just
proceeded on to return "No Result." We can ignore the issues with
result for now. ;-)

Anyone got any ideas? Being stuck in state NEW just confuses the heck
out of me. Did I blow a conditional test somewhere?
 
D

Daniel Pitts

Hi all, I was planning on doing some swing testing, but ran into a
thread issue instead. The problem is a small anonymous thread class I
create stays stuck in state NEW, even though it apparently runs an
completes.

package crazythreads;

import javax.swing.JOptionPane;

public class Main
{
public static void main(String[] args)
{
Main test = new Main();
System.out.println( test.thready() );
}

private String thready()
{
String result = null;
Thread t = new Thread(){
public void run() {
//result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null,"Enter a random string:");
}
};
javax.swing.SwingUtilities.invokeLater(t);
try {
while( t.getState() == Thread.State.NEW ) // STUCK HERE
Thread.sleep(100);
while( t.getState() != Thread.State.TERMINATED)
t.join(100);
} catch( Exception ex) {ex.printStackTrace();}
if( result == null )
return "No result.";
return result;
}

}

The debugger shows the main thread stepping through the while loop at
the comment STUCK HERE. The Thread, t, does run: I see it's dialog box
come up, I enter a value and press OK. So it should at some point be in
one of the running states (probably blocked on IO). Before adding the
while loops, the main thread did not wait (at the t.join()) and just
proceeded on to return "No Result." We can ignore the issues with
result for now. ;-)

Anyone got any ideas? Being stuck in state NEW just confuses the heck
out of me. Did I blow a conditional test somewhere?

invokeLater is NOT what you want to do for Thread

invokeLater passes a Runnable object to be executed on the
EventDispatchThread.

Thread happens to implement Runnable, so your code will get called on
the EDT, but your thread object itself doesn't know or care about the
EDT vs its self.

Generally, if you are updating the GUI, you want to create a Runnable
(not thread) and use invokeLater, or invokeAndWait.

Although, I believe the JOptionPane calls are safe to call from any
thread, so you don't need to create a new thread to do so. Double
check the API doc before you take my word on that.
 
E

Eric Sosman

Mark said:
Hi all, I was planning on doing some swing testing, but ran into a
thread issue instead. The problem is a small anonymous thread class I
create stays stuck in state NEW, even though it apparently runs an
completes.

package crazythreads;

import javax.swing.JOptionPane;

public class Main
{
public static void main(String[] args)
{
Main test = new Main();
System.out.println( test.thready() );
}

private String thready()
{
String result = null;
Thread t = new Thread(){
public void run() {
//result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null,"Enter a random string:");
}
};
javax.swing.SwingUtilities.invokeLater(t);
try {
while( t.getState() == Thread.State.NEW ) // STUCK HERE
Thread.sleep(100);
while( t.getState() != Thread.State.TERMINATED)
t.join(100);
} catch( Exception ex) {ex.printStackTrace();}
if( result == null )
return "No result.";
return result;
}
}

The debugger shows the main thread stepping through the while loop at
the comment STUCK HERE. The Thread, t, does run: I see it's dialog box
come up, I enter a value and press OK. So it should at some point be in
one of the running states (probably blocked on IO). Before adding the
while loops, the main thread did not wait (at the t.join()) and just
proceeded on to return "No Result." We can ignore the issues with
result for now. ;-)

Anyone got any ideas? Being stuck in state NEW just confuses the heck
out of me. Did I blow a conditional test somewhere?

The thread `t' never starts at all, hence remains forever
in state NEW. The argument to invokeLater() is not a Thread
per se, but a Runnable (Thread implements Runnable, which is
why the code compiles). invokeLater() arranges for the run()
method of its Runnable to be called by the Event Dispatching
Thread, and its the EDT that displays your JOptionPane. But
the "thread-ness" of t is never used; only its "runnable-ness"
comes into play -- and on a different thread, at that.

What are you trying to accomplish with this JOptionPane?
Yes, you said to "ignore the issues with result for now," but
I suspect those very issues are central to finding the right
solution.
 
S

SadRed

Hi all, I was planning on doing some swing testing, but ran into a
thread issue instead. The problem is a small anonymous thread class I
create stays stuck in state NEW, even though it apparently runs an
completes.
package crazythreads;
import javax.swing.JOptionPane;
public class Main
{
public static void main(String[] args)
{
Main test = new Main();
System.out.println( test.thready() );
}
private String thready()
{
String result = null;
Thread t = new Thread(){
public void run() {
//result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null,"Enter a random string:");
}
};
javax.swing.SwingUtilities.invokeLater(t);
try {
while( t.getState() == Thread.State.NEW ) // STUCK HERE
Thread.sleep(100);
while( t.getState() != Thread.State.TERMINATED)
t.join(100);
} catch( Exception ex) {ex.printStackTrace();}
if( result == null )
return "No result.";
return result;
}

The debugger shows the main thread stepping through the while loop at
the comment STUCK HERE. The Thread, t, does run: I see it's dialog box
come up, I enter a value and press OK. So it should at some point be in
one of the running states (probably blocked on IO). Before adding the
while loops, the main thread did not wait (at the t.join()) and just
proceeded on to return "No Result." We can ignore the issues with
result for now. ;-)
Anyone got any ideas? Being stuck in state NEW just confuses the heck
out of me. Did I blow a conditional test somewhere?

invokeLater is NOT what you want to do for Thread

invokeLater passes a Runnable object to be executed on the
EventDispatchThread.

Thread happens to implement Runnable, so your code will get called on
the EDT, but your thread object itself doesn't know or care about the
EDT vs its self.

Generally, if you are updating the GUI, you want to create a Runnable
(not thread) and use invokeLater, or invokeAndWait.

Although, I believe the JOptionPane calls are safe to call from any
thread, so you don't need to create a new thread to do so. Double
check the API doc before you take my word on that.

Daniel Pitts is right.
OP's Thread t is never run, so it remains NEW state indefinitely. A
thread that involeLater() would make, in which the JOptionPane is
instantiated, is completely different from the Thread t of the Main
class.
 
M

Mark Space

Daniel said:
invokeLater is NOT what you want to do for Thread

invokeLater passes a Runnable object to be executed on the
EventDispatchThread.

Hmm, ok, I see what you mean. Considering all I'm doing is waiting,
invokeAndWait makes sense. However, the other thing you are saying
about Thread implementing Runnable: you mean Thread is bypassed, no
..start() is called and all of it's state info is useless? Thats.. kinda
weird. Anyone know, mechanically, how the EDT does this?

Later, JOptionPane will be replaced by a custom JFrame. It's just a
placeholder in the example for now, so blocking or safe or not, it
doesn't matter. I do need to return a value somehow, so that's next to
work on.
 
T

Tom Hawtin

Mark said:
Hi all, I was planning on doing some swing testing, but ran into a
thread issue instead. The problem is a small anonymous thread class I
create stays stuck in state NEW, even though it apparently runs an
completes.
Thread t = new Thread(){
javax.swing.SwingUtilities.invokeLater(t);

SwingUtilities (or better java.awt.EventQueue) .invokeLater takes a
Runnable argument, which by a piece of terrible design is implemented by
Thread. It calls run on the argument, in the Event Dispatch Thread
(EDT). In order for your thread to start, Thread.start would need to be
called.

(
You can pick up these sort of problems by using a subclass of Thread
that does not allow itself to be used as a Runnable.

http://groups.google.com/group/comp...6?lnk=st&q=SafeThread&rnum=3#e634f82ccd1161a6
)

So, replace Thread with plain Runnable.

The easiest way to get the calling thread to wait is to use
EventQueue.invokeAndWait instead of invokeLater, although it does add
checked exceptions that need to be dealt with.

There are a number of ways to get results back from Runnable. The
obvious way is to go one level up from an anonymous inner class and use
a local class.

class InputDialogTask implements Runnable {
String result;
public void run() {
result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null, "Enter a random string:"
);
}
}
InputDialogTask inputDialogTask = new InputDialogTask();
java.awt.EventQueue.invokeAndWait(inputDialogTask);
return inputDialogTask.result;

If you don't mind being a little obscure, you can do it in a terser fashion.

return new Runnable() {
String result;
public void run() {
result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null, "Enter a random string:"
);
}
// (this is an instance initialiser)
{
java.awt.EventQueue.invokeAndWait(this);
}
}.result;

Alternatively, a more sophisticated approach is to have the main thread
waiting on a (java.util.concurrent) blocking queue. This could be
extended to make the main thread become event based (not shown).

final BlockingQueue<String> resultQueue =
new ArrayBlockingQueue<String>(1);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
String result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null, "Enter a random string:"
);
resultQueue.add(result);
}
});
return resultQueue.take(); // blocks

(Disclaimer: Not tested or even compiled.)

Tom Hawtin
 
T

Tom Hawtin

Daniel said:
Although, I believe the JOptionPane calls are safe to call from any
thread, so you don't need to create a new thread to do so. Double
check the API doc before you take my word on that.

No.

"Warning: Swing is not thread safe. For more information see Swing's
Threading Policy."

("Swing's Threading Policy" shows you how to write code that doesn't
compile:)

As it happens JDialog extends Dialog which has handling for being called
off the EDT. So it may well appear to work. However, it's not safe at all.

Tom Hawtin
 
M

Mark Space

Tom said:
Thread. It calls run on the argument, in the Event Dispatch Thread

Ok, I think I get it. The EDT just calls run() directly, achieving
synchronization by running the code in it's own thread. Gotcha. Now I
understand why Thread was never invoked with start().

There are a number of ways to get results back from Runnable. The
obvious way is to go one level up from an anonymous inner class and use
a local class.

I'd thought of this, but I didn't have any need for a local class, and
an anonymous class seemed to fit the overall design better.

If you don't mind being a little obscure, you can do it in a terser
fashion.

return new Runnable() {
String result;
public void run() {
result = (String)JOptionPane.showInputDialog(
JOptionPane.showInputDialog(
null, "Enter a random string:"
);
}
// (this is an instance initialiser)
{
java.awt.EventQueue.invokeAndWait(this);
}
}.result;

Wooooooow, smmmooooooottttthhhhh!! I'm highly impressed. Just the sort
of trick I was looking for.
Alternatively, a more sophisticated approach is to have the main thread
waiting on a (java.util.concurrent) blocking queue. This could be
extended to make the main thread become event based (not shown).

I thought of this too, but declaring a concurrent object that going to
be used once, for one piece of data, seemed a little "heavy weight" to
me. It or the local class thing was going to be my "last ditch" effort.

Thanks for that great summary of ideas!!
 
T

Tom Hawtin

Mark said:
I thought of this too, but declaring a concurrent object that going to
be used once, for one piece of data, seemed a little "heavy weight" to
me. It or the local class thing was going to be my "last ditch" effort.

IMO, using multiple threads is a bit heavyweight. Once you have multiple
threads, BlockingQueue is remarkably lightweight (certainly beats
playing with locks directly).

Tom Hawtin
 
M

Mark Space

Tom said:
IMO, using multiple threads is a bit heavyweight. Once you have multiple
threads, BlockingQueue is remarkably lightweight (certainly beats
playing with locks directly).

I do appreciate your replies; I'll describe briefly why. The code I
posted was just a demo. In the final application, I'll already have
multiple threads, plus the EDT, and I assume no choice but to
synchronize with it. I don't see any other way. Any random thread
might invoke the equivalent of "main," and then I'll have to put up a
window, get a result, and return it to the random thread.

If you're referring to my initial use of the Thread class, yes, that was
a conceptual error. ;-)
 
D

Daniel Pitts

No.

"Warning: Swing is not thread safe. For more information see Swing's
Threading Policy."

("Swing's Threading Policy" shows you how to write code that doesn't
compile:)

As it happens JDialog extends Dialog which has handling for being called
off the EDT. So it may well appear to work. However, it's not safe at all.

Tom Hawtin

Ah, actually what threw me off was the fact that JOptionPane modal
dialogs block the current thread. automatically. I guess they push a
new EDT thread onto some sort of stack to handle this case.
 
T

Tom Hawtin

Ah, actually what threw me off was the fact that JOptionPane modal
dialogs block the current thread. automatically. I guess they push a
new EDT thread onto some sort of stack to handle this case.

It's behaviour implemented in Dialog (and other parts of AWT). There's
Swing code in JOptionPane that is done entirely outside of that.

With modal Dialogs there are two ways it can go, depending upon whether
it is in the EDT or not.

If a modal Dialog is shown off the EDT, the current thread just waits.
(You can abuse this behaviour to do certain things from EDT thread that
you otherwise shouldn't. However, EventQueue.isDispatchThread and the
like will be inappropriate.) This should not be done with Swing components.

If a modal Dialog is shown on the EDT, a new event loop is run. That
services events for the current dialog, and allows certain events
through to other windows (repaints but not mouse motion, for instance).

IMO, modal user interfaces are poor anyway.

Tom Hawtin
 

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,773
Messages
2,569,594
Members
45,120
Latest member
ShelaWalli
Top