danger JLabel.settext() in another thread

Y

Yamin

Hey all,

I was wondering how dangerous calling JLabel.setText from a thread
other than the event dispatching thread. I know its illegal, but its
in there. I'm looking at some code which does this, but so far it has
not caused any problems and its passed testing.

Basically, it's just a thread that updates the elapsed time. Don't
ask me why its in its own thread...I didn't write it.


Yamin
 
R

Remi Bastide

What about :

SwingUtilities.invokeLater(
new Runnable() {
public void run() {
myLabel.setText("hello");
}
}
}

?
 
M

Matt Humphrey

Yamin said:
Hey all,

I was wondering how dangerous calling JLabel.setText from a thread
other than the event dispatching thread. I know its illegal, but its
in there. I'm looking at some code which does this, but so far it has
not caused any problems and its passed testing.

Basically, it's just a thread that updates the elapsed time. Don't
ask me why its in its own thread...I didn't write it.

It's illegal because it will eventually conflict with whatever Swing is
doing. Although setting text seems simple, Swing is accessing font sizes,
graphics contexts and so forth. Having the underlying string (reference)
change may cause any number of problems. In my experience with this
particular case (which was a while ago), I usually end up with the label
truncated, not resizing and possibly with unexplained crashes. Because the
symptoms depend strongly on the timing within the virtual machine, and other
platform-dependent things, you may not see any problems until your customer
runs the program on a different machine.

Cheers,

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
R

Roedy Green

I was wondering how dangerous calling JLabel.setText from a thread
other than the event dispatching thread. I know its illegal, but its
in there. I'm looking at some code which does this, but so far it has
not caused any problems and its passed testing.


Unlike the AWT, Swing is not threadsafe. You can't directly meddle
with Swing components, or their backing data models from a second
thread. The contract is, if you want to do anything to a Swing
component that could have any effect on it's display from an
application thread (not the EventDispatchThread itself), you should
add it to the event dispatch thread's queue via
SwingUtilities.invokeLater( Runnable ) or
SwingUtilities.invokeAndWait( Runnable ) so that it will be done on
the same thread that Swing itself uses. The good news is, even though
you are using Runnable, you don't have the overhead of actually
creating a new Thread since you are just calling the run method on the
already existing Swing thread.

There are a few exceptions to this general rule, most notably it is
safe to call repaint and revalidate, JTextComponent.setText and
JTextArea.append from any thread.

See http://mindprod.com/jgloss/threadsafe.html
 
S

Sam

Roedy Green said:
Unlike the AWT, Swing is not threadsafe. You can't directly meddle
with Swing components, or their backing data models from a second
thread. The contract is, if you want to do anything to a Swing
component that could have any effect on it's display from an
application thread (not the EventDispatchThread itself), you should
add it to the event dispatch thread's queue via
SwingUtilities.invokeLater( Runnable ) or
SwingUtilities.invokeAndWait( Runnable ) so that it will be done on
the same thread that Swing itself uses. The good news is, even though
you are using Runnable, you don't have the overhead of actually
creating a new Thread since you are just calling the run method on the
already existing Swing thread.


Let me see if I have this straight. Say you have an app that creates a
GUI to display something like the amount of data being processed by a
NIC card. To monitor this card, you start a thread, passing to it a
reference to the GUI you just created in the main thread
(EventDispatchThread, presumably). The monitoring thread needs to
continually update the GUI with data as it observes it.

Does the above reference mean the monitoring thread can't just update
the GUI even though it has a direct reference to it? For example, to
change a JTextBox on the GUI to say "100 packets received", do I have
to create runnable class, which nonetheless won't be invoked at the
start of a thread, which updates the JTextBox, and then make it a
parameter to either either invokeLater or invokeAndWait, instead of
updating JTextBox directly?

Is it possible for Sun have thought up a less intuitive way to do
this?

Regards,
Sam90
 
R

Roedy Green

Does the above reference mean the monitoring thread can't just update
the GUI even though it has a direct reference to it?

It has to pass a Runnable that does the gui poking to invokeLater.
There are some exception noted where you can safely do it yourself. I
can see why changing the text in a box is thread safe. All you are
doing is pointing the component to a new string -- an atomic
operation. So long as the paint routine makes it own copy of the
string, all should work.

Yet some other posters have said that these actions are not safe after
all, even if the JavaDoc claims they are.

It never hurts to use a Runnable. It is not that much overhead. It is
not as if you were starting a new thread. The advantage of doing the
Runnable is maintenance. If someone comes along later and changes the
code a little it will still work. Without the Runnable it could stop
working mysteriously, and thread problems are notoriously difficult to
reproduce and track down.
 
M

Matt Humphrey

Let me see if I have this straight. Say you have an app that creates a
GUI to display something like the amount of data being processed by a
NIC card. To monitor this card, you start a thread, passing to it a
reference to the GUI you just created in the main thread
(EventDispatchThread, presumably). The monitoring thread needs to
continually update the GUI with data as it observes it.

Does the above reference mean the monitoring thread can't just update
the GUI even though it has a direct reference to it? For example, to
change a JTextBox on the GUI to say "100 packets received", do I have
to create runnable class, which nonetheless won't be invoked at the
start of a thread, which updates the JTextBox, and then make it a
parameter to either either invokeLater or invokeAndWait, instead of
updating JTextBox directly?

The bigger issue is that the GUI in modern systems accounts for 75%-90% of
the code, so it's not just some little thing that gets updated every so
often. As a complex system in its own right, trying to synchronize it with
application code would be a total nightmare, would likely have bugs and
would have performance problems because of the constant lock checking. By
requiring it be single threaded (except for a couple of methods) Swing can
be much less complex, more robust and have better performance and fewer
opportunities for bugs. Keep in mind that it's only code that runs in
separate threads that needs to deferred to the Event thread. Many apps do
much of their work in the event handler itself where no update is required.
Is it possible for Sun have thought up a less intuitive way to do
this?

I have to admit it took a while to understand what was going on,
particularly because I was raised in the pre-GUI days where a program had
total control of the machine. But now I really like it and having written
many multithreaded (collaborative, distirbuted, etc, etc) systems I would
make the same design decision.

Cheers,

Matt Humphrey (e-mail address removed) http://www.iviz.com/
 
R

Roedy Green

But now I really like it and having written
many multithreaded (collaborative, distirbuted, etc, etc) systems I would
make the same design decision.

Hear Hear! Any time you have race conditions possible, you get into
bugs that only show up on Christmas eve, and then disappear so you
can't nail them. invokeLater is a small penalty to pay for stability
and bug avoidance.

Everything happens on the Swing thread in nice orderly little chunks,
with no unpredictable interleaving.
 
Y

Yamin

Thanks for all the responses guys.
Yeah, I know about invokelater and what not. That's why I asked the
question as I knew of its illegality and how to write it properly.

Its not my code, and sometimes its a mission to get someone to change
something when its 'not broken'.

But I guess the general answer is that its VM specific.

Yamin
 
S

Sam

Matt Humphrey said:
The bigger issue is that the GUI in modern systems accounts for 75%-90% of
the code, so it's not just some little thing that gets updated every so
often. As a complex system in its own right, trying to synchronize it with
application code would be a total nightmare, would likely have bugs and
would have performance problems because of the constant lock checking. By
requiring it be single threaded (except for a couple of methods) Swing can
be much less complex, more robust and have better performance and fewer
opportunities for bugs. Keep in mind that it's only code that runs in
separate threads that needs to deferred to the Event thread. Many apps do
much of their work in the event handler itself where no update is required.


I have to admit it took a while to understand what was going on,
particularly because I was raised in the pre-GUI days where a program had
total control of the machine. But now I really like it and having written
many multithreaded (collaborative, distirbuted, etc, etc) systems I would
make the same design decision.

Cheers,

Matt Humphrey (e-mail address removed) http://www.iviz.com/

Your points are well made and I can see now why they did it that way.
I'd been somewhat mystefied by this I first saw it briefly referred to
in a JMF book last year, and hadn't tracked it down down till now.

Regards,
Sam90
 
S

Sam

Roedy Green said:
It has to pass a Runnable that does the gui poking to invokeLater.
There are some exception noted where you can safely do it yourself. I
can see why changing the text in a box is thread safe. All you are
doing is pointing the component to a new string -- an atomic
operation. So long as the paint routine makes it own copy of the
string, all should work.

Yet some other posters have said that these actions are not safe after
all, even if the JavaDoc claims they are.

It never hurts to use a Runnable. It is not that much overhead. It is
not as if you were starting a new thread. The advantage of doing the
Runnable is maintenance. If someone comes along later and changes the
code a little it will still work. Without the Runnable it could stop
working mysteriously, and thread problems are notoriously difficult to
reproduce and track down.

Thanks for your reply. I was sure there must be a way to make it
simpler from the developer standpoint, but in light of the explanation
I can see why they did that way. This is something I will need to look
out for in the future.

Regards,
Sam90
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top