Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > The invokeLater loop

Reply
Thread Tools

The invokeLater loop

 
 
Stefan Ram
Guest
Posts: n/a
 
      05-10-2013
I invented what I call the »invokeLater loop«:

class Object implements java.lang.Runnable
{ int i = 0;
public void run()
{ java.lang.System.out.println( i++ );
javax.swing.SwingUtilities.invokeLater( this ); }}

public class Main
{ public static void main( final java.lang.String[] args )
{ javax.swing.SwingUtilities.invokeLater( new Object() ); }}

What is it good for?

Maybe it provides a way to loop while still allowing
Swing events to be processed in parallel? (So you do not
always have to spawn another thread besides the EDT.)

One also might see it as a kind of recursion that will not
overflow that stack. But since it does not atually nest
incarnations, it is not really adopted for recursive programming.

 
Reply With Quote
 
 
 
 
Daniel Pitts
Guest
Posts: n/a
 
      05-10-2013
On 5/10/13 11:54 AM, Stefan Ram wrote:
> I invented what I call the »invokeLater loop«:
>
> class Object implements java.lang.Runnable
> { int i = 0;
> public void run()
> { java.lang.System.out.println( i++ );
> javax.swing.SwingUtilities.invokeLater( this ); }}
>
> public class Main
> { public static void main( final java.lang.String[] args )
> { javax.swing.SwingUtilities.invokeLater( new Object() ); }}
>
> What is it good for?
>
> Maybe it provides a way to loop while still allowing
> Swing events to be processed in parallel? (So you do not
> always have to spawn another thread besides the EDT.)
>
> One also might see it as a kind of recursion that will not
> overflow that stack. But since it does not atually nest
> incarnations, it is not really adopted for recursive programming.
>


A few comments:

That's isn't really a new invention.

It isn't recursive.

It encourages coupling the application logic to the UI environment.

It is a good way to eat up CPU cycles if you don't want to have your CPU
go idle. Also known as a laptop warmer.

It doesn't take advantage of concurrent processing capabilities of most
modern systems, ultimately slowing down both your EDT and your
application processing.

It is more error prone and harder to tune than using a SwingWorker.

Unrelated to the point you made Stefan, I feel I should make a note on
Stefan Ram(TM) convention. When I see "new Object()", and it isn't
referring to java.lang.Object, it takes me 10 times as long to
understand what the code is doing. I literally stared at that for 3 or 4
seconds before it clicked that you were using confusing class names and
hoping your abstruse convention would "clarify" the confusion.


 
Reply With Quote
 
 
 
 
Stefan Ram
Guest
Posts: n/a
 
      05-10-2013
Daniel Pitts <(E-Mail Removed)> writes:
>It is a good way to eat up CPU cycles if you don't want to have your CPU
>go idle. Also known as a laptop warmer.


Say, I am writing an implementation of the »Game Of Life«. I have an
endless main loop whose contents updates to the next generation.

I want to have a sequence like:

- calculate next generation
- update screen
- calculate next generation
- update screeen
- calculate next generation
- ...

I think that I can do this by calculating the next generation and
updating the screen in »paintComponent« and then »invokingLater«
paintComponent or requesting a screen update which indirectly will
call »paintComponent« again. This will give the sequence above.

Another possibility might be to calculate the next generation in
a separate thread (SwingWorker). But I am not sure how to get
the above sequence (without waiting an arbitrary period of
times or complicated handshaking across thread boundaries).

 
Reply With Quote
 
Daniel Pitts
Guest
Posts: n/a
 
      05-10-2013
On 5/10/13 12:40 PM, Stefan Ram wrote:
> Daniel Pitts <(E-Mail Removed)> writes:
>> It is a good way to eat up CPU cycles if you don't want to have your CPU
>> go idle. Also known as a laptop warmer.

>
> Say, I am writing an implementation of the »Game Of Life«. I have an
> endless main loop whose contents updates to the next generation.
>
> I want to have a sequence like:
>
> - calculate next generation
> - update screen
> - calculate next generation
> - update screeen
> - calculate next generation
> - ...
>
> I think that I can do this by calculating the next generation and
> updating the screen in »paintComponent« and then »invokingLater«
> paintComponent or requesting a screen update which indirectly will
> call »paintComponent« again. This will give the sequence above.

Depending on the type of simulation, you might not actually want to wait
for the screen to update before continuing. This is actually
particularly true in multi-player games. GoL may be an exception of
course, since typically users do want to see every frame.

By the way, calling "repaint()" doesn't mean the screen is updated.
You'd have to be actively updating the screen each loop.

> Another possibility might be to calculate the next generation in
> a separate thread (SwingWorker). But I am not sure how to get
> the above sequence (without waiting an arbitrary period of
> times or complicated handshaking across thread boundaries).
>

Calling SwingWorker.invokeAndWait() isn't that complicated of a boundary
IMO.

public class GoLMain {
public static void main(String...args) {
GameOfLifeSimulation gols = new GameOfLifeSimulation();
GolUI ui = initUi();
while (true) {
Generation g = gols.nextGeneration();
SwingUtilities.invokeAndWait(ui.generationPainterF or(g));
}
}
}



 
Reply With Quote
 
Joerg Meier
Guest
Posts: n/a
 
      05-10-2013
On Fri, 10 May 2013 12:18:15 -0700, Daniel Pitts wrote:

> Unrelated to the point you made Stefan, I feel I should make a note on
> Stefan Ram(TM) convention. When I see "new Object()", and it isn't
> referring to java.lang.Object, it takes me 10 times as long to
> understand what the code is doing. I literally stared at that for 3 or 4
> seconds before it clicked that you were using confusing class names and
> hoping your abstruse convention would "clarify" the confusion.


By this point, that must be intentional obfuscation, outright designed and
intended to cause bugs and present a maintenance nightmare, and you won't
convince me otherwise. Overwriting "Object" is so purely malicious that
there is no way that it's just random ineptitude, especially not from
Stefan, who certainly isn't clueless enough to not be aware of that.

My best guess would be that it's a straw man in the hopes of someone
complaining about a bug it caused, which could then be responded to with
something along the lines of "If only you would fully qualify every class
reference like me, this wouldn't have happened to you, this proves that
imports are evil".

But since Stefan generally does not address criticism of his coding style,
we will most likely forever be left to wonder what particular insanity
sparks the Stefan Ram(TM) convention

Liebe Gruesse,
Joerg

--
Ich lese meine Emails nicht, replies to Email bleiben also leider
ungelesen.
 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      05-10-2013
On 5/10/2013 3:40 PM, Stefan Ram wrote:
> Daniel Pitts <(E-Mail Removed)> writes:
>> It is a good way to eat up CPU cycles if you don't want to have your CPU
>> go idle. Also known as a laptop warmer.

>
> Say, I am writing an implementation of the »Game Of Life«. I have an
> endless main loop whose contents updates to the next generation.
>
> I want to have a sequence like:
>
> - calculate next generation
> - update screen
> - calculate next generation
> - update screeen
> - calculate next generation
> - ...
>
> I think that I can do this by calculating the next generation and
> updating the screen in »paintComponent« and then »invokingLater«
> paintComponent or requesting a screen update which indirectly will
> call »paintComponent« again. This will give the sequence above.


How long does "calculate the next generation" take?

- If it takes "significant" time, you're tying up the EDT
and making the GUI unresponsive during the calculation.

- If it takes "insignificant" time, you might as well just
go ahead and do the deed without all the fuss and bother.

Either way, I see no use case for the scheme. (Also, I don't
think you can rely on having one paintComponent() call per update:
If your GUI gets minimized everything might just freeze, or if
another window obscures part of your GUI you might get multiple
paintComponent() calls to refresh the display, or multiple calls
with different clip regions to paint around the intruder. You
need some extra work to make sure paintComponent() only calls
invokeLater() "when appropriate.")

> Another possibility might be to calculate the next generation in
> a separate thread (SwingWorker). But I am not sure how to get
> the above sequence (without waiting an arbitrary period of
> times or complicated handshaking across thread boundaries).


Leapfrogging a Runnable from EDT moment to EDT moment with
multiple invokeLater() self-invocations ... What a splendid way
to avoid complication!

It'd be simple enough to do it with a SwingWorker, if you
wanted to. The GUI would create a SwingWorker instance to compute
one generation and call execute() to start it, running its
doInBackground() method on a worker thread. When doInBackground()
finishes, the SwingWorker's done() method runs on the EDT, where
it can paint the display, and create and launch another SwingWorker
for the next generation. Easy-peasy.

Personally, I'd do it by driving things from the calculation
thread: Compute a new generation, compute the changes, send the
changes to the EDT via invokeLater() while the calculation thread
starts work on the next generation. Easy to control the frames-
per-second rate, too, which I think would be horribly difficult
using EDT-multiplexing.

Perhaps there's an application for the leapfrog technique, but
I've not yet heard or thought of one.

--
Eric Sosman
http://www.velocityreviews.com/forums/(E-Mail Removed)d
 
Reply With Quote
 
Daniele Futtorovic
Guest
Posts: n/a
 
      05-10-2013
On 10/05/2013 21:40, Stefan Ram allegedly wrote:
> Daniel Pitts <(E-Mail Removed)> writes:
>> It is a good way to eat up CPU cycles if you don't want to have your CPU
>> go idle. Also known as a laptop warmer.

>
> Say, I am writing an implementation of the »Game Of Life«. I have an
> endless main loop whose contents updates to the next generation.
>
> I want to have a sequence like:
>
> - calculate next generation
> - update screen
> - calculate next generation
> - update screeen
> - calculate next generation
> - ...
>
> I think that I can do this by calculating the next generation and
> updating the screen in »paintComponent« and then »invokingLater«
> paintComponent or requesting a screen update which indirectly will
> call »paintComponent« again. This will give the sequence above.


Not sure I get this. If you are performing non-UI-related computations
in your "Object" (I second Daniel's remarks on your choice of
nomenclature, btw), then these will happen on the EDT. But they should
actually be happening /off/ the EDT.

So it seems to me either you are busying the EDT and lagging the app, or
it's really just a laptop warmer. Perhaps another example would be useful.

--
DF.
 
Reply With Quote
 
markspace
Guest
Posts: n/a
 
      05-10-2013
On 5/10/2013 11:54 AM, Stefan Ram wrote:
>
> Maybe it provides a way to loop while still allowing
> Swing events to be processed in parallel? (So you do not
> always have to spawn another thread besides the EDT.)


Swing events can't be processed in parallel, they're run on a single thread.


 
Reply With Quote
 
Silvio
Guest
Posts: n/a
 
      05-10-2013
On 05/10/2013 08:54 PM, Stefan Ram wrote:
> I invented what I call the »invokeLater loop«:
>
> class Object implements java.lang.Runnable
> { int i = 0;
> public void run()
> { java.lang.System.out.println( i++ );
> javax.swing.SwingUtilities.invokeLater( this ); }}
>
> public class Main
> { public static void main( final java.lang.String[] args )
> { javax.swing.SwingUtilities.invokeLater( new Object() ); }}
>
> What is it good for?
>
> Maybe it provides a way to loop while still allowing
> Swing events to be processed in parallel? (So you do not
> always have to spawn another thread besides the EDT.)
>
> One also might see it as a kind of recursion that will not
> overflow that stack. But since it does not atually nest
> incarnations, it is not really adopted for recursive programming.
>


What is with this horrible code layout. Really makes makes me not want
to read the code.
 
Reply With Quote
 
Daniel Pitts
Guest
Posts: n/a
 
      05-10-2013
On 5/10/13 3:26 PM, Silvio wrote:
> [snip]
> What is with this horrible code layout. Really makes makes me not want
> to read the code.


Don't bother, Stefan is a long time poster refusing to cater to this
audience.

It is better than some, however. Not quite "troll level". Try reading
some of qwertymonkey's code for instance.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Windows 8 - so bad it's hastening the death of the PC? ~misfit~ NZ Computing 18 04-15-2013 04:15 AM
Triple nested loop python (While loop insde of for loop inside ofwhile loop) Isaac Won Python 9 03-04-2013 10:08 AM
Can someone use invokeLater() to call a public method from a JPanel? ***C.Steamer*** Java 39 10-29-2004 02:00 PM
SwingUtilities.invokeLater Ike Java 2 10-08-2003 08:47 PM
InvokeLater Mohit Gupta ASP .Net 0 07-11-2003 07:34 AM



Advertisments