File browser

L

Lew


How long did that take to Google up? Not very, I'll wager.

Lew:
Peter said:
I'm not talking about "running events".

Not "events" in the sense of EventListener, but events like calling a method,
which you do when you invoke, e.g., "new JFrame()".
If you have a point to make, surely you have some reference that supports the point.

Op. cit. upthread.
Telling someone to Google for that reference when you already know what it is is just lame.

Why do you think that pertains? If I already knew what it was I certainly
would have posted it, and did, for one such. What's lame about that? I
simply said that there's more evidence out there and it can be found. RGB's
rapid discovery of a relevant article is evidence for that. Now let's move
off the /ad hominem/ arguments and stick to the topic, hm?

Peter:
But as far as initialization goes, there's ample ambiguity here, in the documentation,
in the tutorials, and in sample code I've seen all over the place.

Information that was published before Sun realized, as they now shamefacedly
admit, that they've been putting out wrong information.

Just look at how long people still cite Vector and Hashtable, classes that
were supplanted in 1998 before most practitioners today had learned Java, to
see how long it takes old information to vanish.

The presence of wrong information out there doesn't make bad practices viable.

Here's the salient quote from RedGrittyBrick's JavaWorld link:
The correct way to start up a Swing GUI today differs from Sun's originally prescribed approach.
Here's the quote from the Sun documentation again:

Once a Swing component has been realized, all code that might affect or depend on the state
of that component should be executed in the event-dispatching thread.

Now throw those instructions out the window, because around when JSE 1.5 was released all the
examples on Sun's site changed. Since that time it has been a little-known fact that you are
supposed to always access Swing components on the event-dispatch thread to ensure their thread
safety/single-threaded access. The reason behind the change is simple: while your program might
access a Swing component off of the event-dispatch thread before the component is realized, the
initialization of the Swing UI could trigger something to run on the event-dispatch thread
afterward, because the component/UI expects to run everything on the event-dispatch thread.
Having GUI components run on different threads breaks Swing's single-threaded programming model.

That should give you the hints you need to construct an example that fails if
you don't initialize on the EDT.
 
L

Larry A Barowski

Peter Duniho said:
On Tue, 05 Feb 2008 16:16:42 -0800, Peter Duniho
Ah, posted too soon. The dialog that shows up by default with the
JFileChooser does share the layout with the "metal" dialog, but it's
otherwise a regular Mac dialog. I did try explicitly setting the "metal"
look-and-feel and on the Mac, that produces yet another result: a dialog
that looks much more like the Windows "metal" dialog, and which also works
correctly.

So now you know where to report the bug. Unless I am
missing something, there seems to be no way to search
for bugs on ADC, but you can report them.
Unfortunately, the "metal" look is much too much out of place on the Mac.
Even on Windows, it's a bit of a stretch, but it just doesn't work at all
on the Mac. I'm afraid I'm back to sticking with the AWT dialog.

Over the years, I've found the Mac L&Fs to be flaky
and unreliable in general. The system menu and
desktop pane / internal frames have been especially
problematic. When you work around all the problems,
another one pops up in the next Mac Java release. For
that reason, our product defaults to Metal on the Mac,
and doesn't use the system menu if the user switches
to the Mac L&F.
 
L

Larry A Barowski

Peter Duniho said:
You seem to be confusing the general issue of use of components with the
specific scenario I'm talking about: creating the components off the EDT.

I am willing to take as granted that one must always use components after
initialization in the EDT. There are in fact statements to this effect in
the actual Java API documentation, and that's good enough for me.

But as far as initialization goes, there's ample ambiguity here, in the
documentation, in the tutorials, and in sample code I've seen all over the
place. I've been writing Java code for a month, and this is the first
I've seen of any suggestion that _initialization_ is also required to be
done on the EDT. And it's not from lack of exposure to the documentation
or to sample code.

Your program may work fine on every system and every
Java version you have available. On some other system
or some other Java version, or some future version of
Java on your own system, or once every million runs on
your old system, it may crash. We had a program that
initialized a splash screen on the main thread - the rest
was on the EDT. Because of that, it failed about once
every 100,000 times at startup. Fortunately we have
automatic error reporting, or we might never have
known.
 
L

Lew

Peter said:
You seem to be confusing the general issue of use of components with the
specific scenario I'm talking about: creating the components off the EDT.

No, I am speaking specifically of creating components off the EDT, and have
been for a couple of posts now.
I'm quite familiar with Google. I've been Googling Java issues for a month now.
But Google is not a great resource when one has already Googled and as a result of
failing to find sought-after information has posted a question to a newsgroup.

If Google fails you try searching within Sun's Java site or IBM DeveloperWorks
for Java questions. Five minutes on Sun turned up this gem:

You must create and initialize your GUI on the Swing event dispatch thread (EDT).
Many application developers forget this important step.

This article doesn't explain that as well as the JavaWorld article
RedGrittyBrick found but it should tip you off that there's something to this
matter.

Note that the article I found, and the JavaWorld article both date from
mid-2007. That is around the time the error in previous advice started
getting the publicity it deserved.

Here's an "Ask the Expert" from Sun's website:
Until recently, the Swing claim was that GUIs could be constructed and accessed on any thread
up until the time that they were realized (a call to setVisible(true) realizes a frame and the
components it contains). After being realized, all GUI interaction would then need to happen
on the event dispatch thread (EDT). As such, calling setVisible(true) from the constructor
would simply mean that any further interaction with the component would have to occur on the EDT.

Recently, Swing has updated our policy to say that ALL Swing interaction must now be done on the
EDT for both unrealized and realized components. This includes GUI construction. When this policy
is followed, it makes absolutely no difference (from a safety perspective) where you call
setVisible(true). Please see the document How to Use Threads
for more information on threads and Swing.

That link throws back into the tutorial, which among other things states:
Why doesn't the initial thread simply create the GUI itself?
Because almost all code that creates or interacts with Swing components must run on the event
dispatch thread. ....
Programs that ignore this rule may function correctly most of the time, but are subject to
unpredictable errors that are difficult to reproduce.

Note that they say "creates ... Swing components".

That "difficult to reproduce" thing does not make the issue less valid, but it
might pose you difficulty in your quest for examples.
 
P

Patricia Shanahan

Peter Duniho wrote:
....
I don't think I can fully understand the recommendation or the assertion
that something might break until I know exactly how it would break and
under what circumstances that might happen.
....

I tend to look at thread interaction issues the other way round. I don't
think I can fully understand a recommendation to do something in a
different thread unless I know exactly why it is guaranteed to work.

Patricia
 
N

Nigel Wade

Peter said:
You seem to be confusing the general issue of use of components with the
specific scenario I'm talking about: creating the components off the EDT.

I am willing to take as granted that one must always use components after
initialization in the EDT. There are in fact statements to this effect in
the actual Java API documentation, and that's good enough for me.

But as far as initialization goes, there's ample ambiguity here, in the
documentation, in the tutorials, and in sample code I've seen all over the
place. I've been writing Java code for a month, and this is the first
I've seen of any suggestion that _initialization_ is also required to be
done on the EDT. And it's not from lack of exposure to the documentation
or to sample code.


I'm not talking about "running events".


Such as? I can reproduce synchronization problems at will in other
contexts, through careful control of the threads involved (i.e. putting in
different synchronization that ensures things happen in the wrong order).
Under what circumstances is it _guaranteed_ that initializing my GUI
components off the EDT will cause trouble? Please provide sufficiently
detailed information such that it would allow me to write sample code to
reproduce the trouble.


No doubt. But that's not the question here.


I'm quite familiar with Google. I've been Googling Java issues for a
month now. But Google is not a great resource when one has already
Googled and as a result of failing to find sought-after information has
posted a question to a newsgroup.

If you have a point to make, surely you have some reference that supports
the point. Telling someone to Google for that reference when you already
know what it is is just lame. Asserting a point when you don't actually
have a reference that supports the point is also lame. Making a point and
providing a reference, that's actually quite nice and helpful behavior.


You must use synchronization. So?


I can easily write code that will consistently produce wrong results with
incorrect synchronization. It's true that one can get lucky and have it
work without. But it's also true that it's relatively simple to force a
problem in order to demonstrate the risk of failing to synchronize.

Yes, but to do that you need to be in control of the competing threads. With the
EDT you are not.
So, how can I force a problem to demonstrate that my GUI initialization
must occur on the EDT? How can I write a program that initializes the GUI
off the EDT, and in doing so consistently suffers from whatever problem it
is that you're saying could happen if I do that?

You can't force it, you're not in control. The environment is not consistent, so
the results won't be. The problem with threads is that you are not in control
of when they execute, other than via synchronization techniques. Swing is not
synchronized and is therefore not thread safe. You don't control when the EDT
starts and you don't control what it does to the GUI components, or when. It's
not reliably reproducible because you can't control the execution of the EDT.
The EDT is event driven, events which are affected by user actions and the
exact timing of those actions, plus other factors external to your application
which are handled by the OS.
I don't think I can fully understand the recommendation or the assertion
that something might break until I know exactly how it would break and
under what circumstances that might happen.

You might not be able to provide that information, and if so that's fine.
But please don't make it sound like I have no reason to seek or receive
that information.

Happy searching.
 
D

Daniel Pitts

Daniele said:
Well, you tried doing the initial GUI setup in the main thread and
showing it there, didn't you? It works. Consequently it's not a MUST
rule as the examples of the Win and Mac API you spoke of.
As a matter of fact, you probably would get an application to run
properly even if you ignored that rule -- provided you didn't went
overboard with threads, mayhap issued a supplementary repaint() or two
here and there and, most importantly, ran on a single core CPU.
Actually, when you use Swing, you are using more than one thread
automatically. The main thread and the EDT. When ever more than one
thread is involved, you *must* use proper synchronization to be safe.

This must is the same as you must wear a safety belt in a car. You
might get away without it most of the time, but the one time you don't
could be fatal.

Case and point, there was once an automated medical scanning device that
worked 99.9% of the time, but there were a few accidents that no one
could figure out what happened. A few patients died from over-exposure
to radiation. This product of course had been extensively tested and
retested, and worked for so much of the time, but due to a race
condition it could fail (catastrophically) in an unexpected way.

Now, I assume that failure in this case isn't as dangerous, but when
you've been told to wear your safety belt, why shrug it off because
you've survived so far.
BUT...


Not quite. You should know how slippery beasts synchronisation issues (I
do not primarily mean dead-locks or race-conditions, but memory
visibility issues) can be. I don't think it is possible to tell with
sufficient certainty that you won't have synchronisation problems in
your GUI -- given its sheer complexity. I'd venture even someone who'd
have written Swing (presuming it had been written by one single person)
wouldn't be able to tell. Also, keep in mind that Swing components are
unsynchronised by design.
So you MIGHT run into problems, or rather: there most probably WILL be
problems, whether you notice them or not -- the more complex your GUI,
the more you use different threads, the more cores: the more likely --
and such problems as would be *very* difficult to track down.

Therefore: strong recommendation.
Very Very strong.
 
D

Daniel Pitts

Peter said:
[...]
Me, I'm shocked at how hard people resist making programs more
maintainable, and spend many ergs arguing how less safe idioms are
actually acceptable. I guess they never had to maintain software
themselves, or they'd come down a lot more on the side of *good*
practices and *safer* programming idioms.

You are misinterpeting the situation here.

I am not proposing to write code in violation of recommendations. I am
proposing to know the difference between what is guaranteed not to work,
and what is simply recommended so as to ensure something always works
without additional effort.
But hey, argue all you want for unsafe, buggy code idioms. Go for
it. Just don't write any software I have to use, please.

What's the point in implying that people will actually disobey the
recommendation? Trying to get more information in no way implies that
one is going to go off and write software that doesn't comply with the
tutorial's recommendation. And while I intend to take the tutorial's
recommendation seriously, I'll point out that IMHO a tutorial is a long
way off from an API specification or documentation. I've seen far too
many flawed tutorials and code samples to think that a tutorial is the
last word on how to use an API.

Granted, the Java API is not all that thoroughly documented in many
areas, and the tutorials do serve an important role in filling those
gaps. But it's the API documentation that is the last word (well, at
least next-to-the-last word...I suppose the last word is really had by
the implementation itself :) ).

Pete

I think the point that we all need to accept is that code that doesn't
follow this recommendation may /appear/ to work, so in that since it
isn't a must.

The reason that Lew and I have been so vehement about it being a "must"
is that someone who doesn't understand why will read the "it's a
recommendation, not a must", and decide that they don't need to do it
themselves because it works fine. This is faulty reasoning to be sure,
but we want to eliminate all doubt about whether or not you should use
the EDT.

As this is a public forum where plenty of "newbies" look for
information, it is our social responsibility to provide as accurate
information as possible, in as unambiguous way as possible.

To be fair, Swing code *can* appear to work without using the EDT
explicitly, but is just an appearance that could break unexpectedly.
 
D

Daniel Pitts

Peter said:
I don't think I can fully understand the recommendation or the assertion
that something might break until I know exactly how it would break and
under what circumstances that might happen.

You might not be able to provide that information, and if so that's
fine. But please don't make it sound like I have no reason to seek or
receive that information.
The book Java Concurrency in Practice gives an excellent description of
how and why incorrect thread synchronization may cause problems. It is
not expensive as far as books go, and a strong recommendation to read it.

<http://virtualinfinity.net/wordpress/technical-book-recommendations/java-concurrency-in-practice/>
 
P

Peter Duniho

[...]
The reason behind the change is simple: while your program might access
a Swing component off of the event-dispatch thread before the component
is realized, the initialization of the Swing UI could trigger something
to run on the event-dispatch thread afterward, because the component/UI
expects to run everything on the event-dispatch thread. Having GUI
components run on different threads breaks Swing's single-threaded
programming model.

That should give you the hints you need to construct an example that
fails if you don't initialize on the EDT.

I don't see how it does. What part of my initialization "could trigger
something to run on the EDT", before I've actually shown any of the UI?
Why would you think that I could just develop a complete example of a
reliably broken program from that information alone? And more importantly
to me, if someone else can't state in a simple way what might "trigger
something to run on the EDT" before any of my components are shown, why
should I think that the statement that it could happen is reliable?

Honestly, I've never run into such a resistance to having something
actually _explained_, except when the person doing the explaining isn't
actually sure themselves of what they are trying to say. I am starting to
suspect that you have no concrete idea of what might actually go wrong.

There's nothing wrong with that per se, but please don't act like _I_, a
complete novice to Java, ought to easily be able to find out something
like that when you yourself, an apparent expert in Java, don't know.

Thanks,
Pete
 
P

Peter Duniho

[...]
Recently, Swing has updated our policy to say that ALL Swing
interaction must now be done on the EDT for both unrealized and
realized components. This includes GUI construction. When this policy
is followed, it makes absolutely no difference (from a safety
perspective) where you call setVisible(true). Please see the document
How to Use Threads
for more information on threads and Swing.

"Policy" is not design. And the phrase "it makes absolutely no difference
where you call setVisible(true)" suggests that if you _don't_ follow the
stated policy, it _does_ make a difference where you call
setVisible(true), which in turn implies to at least some degree that it is
possible to call it somewhere that could be safe.

In other words, while that quote (and all the others offered that I've
seen so far) make the same "strong recommendation" being made here, it
doesn't actually document specifically how things might break.

Pardon me if I find such a discussion of the issue incomplete.

Pete
 
P

Peter Duniho

Peter Duniho wrote:
...
...

I tend to look at thread interaction issues the other way round. I don't
think I can fully understand a recommendation to do something in a
different thread unless I know exactly why it is guaranteed to work.

My statement does not exclude yours, nor was it my intent to suggest that
the latter isn't important either.

Pete
 
P

Peter Duniho

So now you know where to report the bug. Unless I am
missing something, there seems to be no way to search
for bugs on ADC, but you can report them.

True on all counts.
Over the years, I've found the Mac L&Fs to be flaky
and unreliable in general. The system menu and
desktop pane / internal frames have been especially
problematic.

For what it's worth, it's not just the look-and-feel stuff I've found to
be unreliable on the Mac. I have run into a number of inconsistencies and
difficulties using Java on the Mac. The most recent being its poor
handling of HTML presentation in components (it doesn't handle the
"&mdash;" character entitity, for example).

I guess that's what happens when most of your client base are people who
have already convinced themselves that everything is inferior to your own
product. They will continue believing that no matter what happens, so why
bother to work hard to make sure things work right?

Pete
 
P

Peter Duniho

[...]
I can easily write code that will consistently produce wrong results
with
incorrect synchronization. It's true that one can get lucky and have it
work without. But it's also true that it's relatively simple to force a
problem in order to demonstrate the risk of failing to synchronize.

Yes, but to do that you need to be in control of the competing threads.
With the EDT you are not.

Sure, you are. Any time you get your code to be called on the EDT, you
are now in control. Until your code returns, you remain in control.

So it should be simple enough to write code that intentionally causes
something to be called on the EDT, at which point one can take advantage
of that control to ensure a synchronization error.

One of the previously-cited articles does in fact do something like this.
Unfortunately, because it's specifically using invokeLater() to get code
to execute on the EDT, it's not a demonstration of the problem I'm asking
about. It does reliably demonstrate the potential for a problem that
could occur when your own code intentially puts something for execution on
the EDT, but it doesn't help me better understand how someone could
unintentionally have something execute on the EDT prior to any components
being visible.
[...]
The EDT is event driven, events which are affected by user actions and
the
exact timing of those actions, plus other factors external to your
application
which are handled by the OS.

Before any components are shown, user actions won't affect when things are
executed on the EDT. So, what of those "factors external to your
application"? What factors exist during initialization, prior to any
components being shown, that might cause something to happen on the EDT?

I should reiterate that none of my questions are intended to suggest that
the advice given is wrong. They are only intended to solicit more
information that would help me understand better what the specific risks
are.

Remember: "I don't know" is an acceptable answer. I just don't appreciate
the attitude conveyed to me that _I_ don't need to know.

Thanks,
Pete
 
F

fchang

I should reiterate that none of my questions are intended to suggest that the
advice given is wrong. They are only intended to solicit more information
that would help me understand better what the specific risks are.

Sharon Zakhour (at Sun) was in charge of updating
Sun's online tutorial to version 1.4.

She found that one of the tutorial would sometimes hang.

After consulting with Scott Violet (from Sun's Swing team),
they finally tracked it down to a "deadlock caused
by creating the GUI on the main thread" (her exact words).

The details are on Sharon's "Java Tutorial" web page at
http://blogs.sun.com/thejavatutorials/entry/a_bit_of_tutorial_history

Also note that this "requirement" is now finally officially
stated in Java SE 6's javadocs.

-
 
L

Lew

Peter said:
if someone else can't state in a simple way what might "trigger something to run on the EDT"
before any of my components are shown,
why should I think that the statement that it could happen is reliable?

Consider the source. (Sun itself, and other authoritative writers.)
Honestly, I've never run into such a resistance to having something
actually _explained_, except when the person doing the explaining isn't
actually sure themselves of what they are trying to say. I am starting
to suspect that you have no concrete idea of what might actually go wrong.

Honestly, I've never run into such a resistance to accepting the explanation,
nor to doing the work necessary to follow through on the material presented.

I know what *might* go wrong - you might have an improper value displayed in a
control, for example. You might have a control not be visible at all - it
depends on the work that's being done.

But I haven't seen these in practice, which is why I give you what I *do* have
a concrete idea of, and that is that reliable, authoritative sources have
stated that the multi-threaded nature of GUIs requires the proper
synchronization. There's no need to go all snarky on me or anyone else here
for trying to help you with the knowledge that we do possess.

I know that the link I posted gave *me* some hints as to how to construct an
example that would display problems if the EDT weren't respected. I'm sorry
that you couldn't get the same value.
 
L

Lew

Peter said:
It does reliably demonstrate the potential for a
problem that could occur when your own code intentially puts something
for execution on the EDT, but it doesn't help me better understand how
someone could unintentionally have something execute on the EDT prior to
any components being visible.

You have it the wrong way 'round. The problem with lack of synchronization
with the EDT is not that we'll have something unintentionally run on the EDT,
it's that we'll not have something run on the EDT that we intended to.
Any time you get your code to be called on the EDT, you are now in control.
Until your code returns, you remain in control.

We do not have control of the EDT because it's run by an autonomic event loop
that is not controlled by the main thread. We only have control of the
callback contexts that we create, but they run under the aegis of the EDT; the
EDT doesn't run under the aegis of any thread we write.

invokeLater() puts the requested functor into the queue, so to speak, for the
event loop to execute at its schedule, not ours as programmers.
 
P

Peter Duniho

[...]
I know what *might* go wrong - you might have an improper value
displayed in a control, for example. You might have a control not be
visible at all - it depends on the work that's being done.

How could those things happen? Specifically, that is, how could those
things happen should I initialize the controls off the EDT?
But I haven't seen these in practice, which is why I give you what I
*do* have a concrete idea of, and that is that reliable, authoritative
sources have stated that the multi-threaded nature of GUIs requires the
proper synchronization. There's no need to go all snarky on me or
anyone else here for trying to help you with the knowledge that we do
possess.

I don't see how you get "snarky" from my replies. I'm simply asking
questions. If you don't know the answer, that's fine. Don't insist that
the questions or their answers are trivial though. That's just silly.
I know that the link I posted gave *me* some hints as to how to
construct an example that would display problems if the EDT weren't
respected. I'm sorry that you couldn't get the same value.

No, you're not. If you were sorry, you would help by pointing out where
in those articles those hints are contained and how to use them to produce
a working sample.

I'm not against doing work, and believe me I've done plenty in my question
to get my Java code to work correctly. But when I know the answer to a
question, I don't sit around telling the person asking the question "I
know the answer, but I refuse to tell you, or even help you understand how
to find the answer from the resources you've been offered". I help the
person learn the answer.

I have already read the references offered and not found the information I
seek. You claim the information is there and imply that it's easily
accessible. If it's so easy, why not just say so? Why waste so much time
refusing to help, when you could instead use that time productively by
helping?

So, either you don't actually know the answer (which is fine, though you
should just admit it so we can forget about worrying whether you'll share
it), or you do. If you do, it's incredibly useless for you to pretend
that you're interested in helping people when at the same time you refuse
to.

Pete
 
P

Peter Duniho

Sharon Zakhour (at Sun) was in charge of updating
Sun's online tutorial to version 1.4.

She found that one of the tutorial would sometimes hang.

After consulting with Scott Violet (from Sun's Swing team),
they finally tracked it down to a "deadlock caused
by creating the GUI on the main thread" (her exact words).

The details are on Sharon's "Java Tutorial" web page at
http://blogs.sun.com/thejavatutorials/entry/a_bit_of_tutorial_history

Thank you, very much, for that information and link. I note that she
writes "Adding this as a requirement was not universally popular, since it
does not affect all programs". In other words, there are actually
predictably safe scenarios...that is, some _programs_ are not affected and
thus it's a matter of the code, not the exact timing of the execution of
the code (as is the situation when there's an actual synchronization
bug). At least that's how I read that.

I would love to learn more about the issue, to find out what specific
scenarios are safe and which ones are not. But I am getting the
impression that it's not a popular topic to discuss and that at least some
people don't share my feeling that it's useful to know how things break,
even if you already know a good rule for avoiding breaking things.

For those who agree that it's useful to know how things break, and/or who
have more specific information on how things might break initializing GUI
components off the EDT thread and are interested in sharing that
information, I welcome any additional input.

Thanks,
Pete
 

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,770
Messages
2,569,583
Members
45,073
Latest member
DarinCeden

Latest Threads

Top