开发者

use of invokeLater

Pretty sure all of these approaches will work, but I'd appreciate opinions on which is the best.

Consider for argument's sake the (unfortunate) scenario where you have UI changing code and reasonably intensive (average 500ms) logic code mixed and inseparable. all of the changing ui components are on the one panel.

01 new Thread(){
02  public void run(){
03 
04  for (int i = 0; i < 100; i++){
05      // some processing
06      doSomething();
07      // update some ui components
08      panel.doSomeUi();
09  }
10 
11  panel.revalidate();
12  panel.repaint();
13 
14 }}.start();

Which of the following 3 approaches would you choose and why?开发者_高级运维

  1. wrap all code in invokeLater
  2. call invokeLater inside doSomeUi() and then again for revalidate/repaint
  3. only use invokeLater for revalidate/repaint at end

For mine:

option 1 would hang the Event Processing Thread (EPT) while all of the processing occurs

option 2 would have overhead considerations with many new runnables being created and in special cases may cause the ui to update in a half complete state if components need some of the subsequent ui changes to be valid

option 3 would be the most efficient but may have some thread safety issues

keen to hear other opinions.


The doSomeUi () some should be wrapped in an invokeLater () and should trigger whatever repaint/redrawing is necessary -- the Swing UI thread will paint while you keep computing.

The overhead of creating a lot of short-lived Runnable's will be tiny on a modern VM, and shouldn't be an issue.

So, option 2 (with suggested modification) should be it. When writing multi-threaded code, slow and correct is always better than fast and randomly buggy.


First of I would get it running single threaded. As an integral part of that I would make sure I had good code (e.g. not extending Thread and JPanel), with good separation of "business" logic and UI, tests, etc. It might not be something impressive, but it is deliverable. Check that into version control. Then perhaps see if there is a small, hot section I can do in parallel.

There are extreme ways of approaching the problem of multithreading. With no shared state we can queue immutable action events out from the UI, and queue immutable update events back in to replace the UI copy of the model. Alternatively we can share state and be very careful with locking (I suggest the biggest locks that could possibly work - careful with callbacks).

It may be useful to note that you don't have to add listeners to every little thing. You can have coarse grain listeners and then rapidly scan through data structures for updates.

An important thing to note is that the actions the UI sends to the "business" model and the state updates in the reverse direction should be as decoupled as possible (i.e. run from SwingWorker).


revalidate and repaint is thread safe. They have their own invokeLater thing built into them, you can call revalidate and repaint from any thread and at any time. It's even so smart made that if you call revalidate a thousand times before it actually validates anything it will put together all those thousand calls into a single call.


Did you read the Java Lesson: Concurrency in Swing and consider using Worker Threads. Also check the TumbleItem Example

The Lesson explicitly says:

Tasks on the event dispatch thread must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive.

and

When a Swing program needs to execute a long-running task, it usually uses one of the worker threads

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜