转自台湾JAVA技术论坛
SwingUtilities 的 invokeAndWait 和 invokeLater [精华]
weaker 小屁屁~ 于 2004-02-17 16:17
--------------------------------------------------------------------------------
这两者有什么差别啊?
看了其 api 还是不太懂
目前我知道的是差别是
invokeAndWait(Runnable r) : 会先等 r 执行完才继续执行
而
invokeLater(Runnable r) : 则是不会等待 r 执行完,而会继续执行下去
其中还有什么的差别吗?
因为再看范例时,有时候范例使用 invokeAndWait
有时则使用 invokeLater ,看了好久看不懂差别在哪
麻烦各位大大帮忙解惑 , thanks !
brianlin 于 2004-02-17 22:20
--------------------------------------------------------------------------------
所有 Swing Component 的绘图动作和 Event 事件的趋动皆是交由 "Event-Dispatching" 这个 Thread 来执行的.
针对 Swing Component 而言, 你不应该在其它的 Thread (如 main thread )对 Swing Component 作重绘的动作(repaint() 动作除外). 如果你执意要在你自已的 Thread 对 Swing Comp 作绘图的动作, 有可能造成不可预期的后果.
所以当你在你自己的 Thread 中经过一些逻辑判断后认为某些 Swing Comp 需要作绘图的动作时, 你可以把你的动作用 Runnable 包装起来透过 SwingUtilties 的 invokeLater() 或是 invokeAndWait() 来执行. 此时 SwingUtilties 会将你的动作放在 "Event-Dispatching" 这个 Thread 来执行 (非你自已的 Thread)
invokeLater() 和 invokeAndWait() 的差别是:
invokeLater() 在你的 Thread 呼叫该 method 后就立刻回来, 不管你指定的动作是否已经被 "Event-Dispatching" 执行.
invokeAndWait() 在你的 Thread 呼叫该 method 后不会立刻回来, 直到你指定的动作已经被 "Event-Dispatching" 执行.
参考:http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
Duncan 又听见妳酸甜甜的声音 版主 于 2004-02-17 22:47
--------------------------------------------------------------------------------
brianlin wrote:
invokeAndWait() 在你的 Thread 呼叫该 method 后不会立刻回来, 直到你指定的动作已经被 "Event-Dispatching" 执行.
最后这一点比较需要注意的是,既然 invokeAndWait method 会 block 直到你要安插到 event-dispatching thread 的动作做完,那么你不应该在 event-dispatching thread 使用这个 method(event-dispatching thread 被 invokeAndWait block 住了,你安插的动作就不可能被执行了,那么 invokeAndWait method 将永远是 block 住的状态)。各种 event listener 所定义 event-handler method 都是执行在 event-dispatching thread,所以当事件发生了,你在 handler method 要作更新 UI 的动作,不需要使用上述提到 method。
brianlin 于 2004-02-17 23:30
--------------------------------------------------------------------------------
Duncan wrote:
最后这一点比较需要注意的是,既然 invokeAndWait method 会 block 直到你要安插到 event-dispatching thread 的动作做完,那么你不应该在 event-dispatching thread 使用这个 method(event-dispatching thread 被 invokeAndWait block 住了,你安插的动作就不可能被执行了,那么 invokeAndWait method 将永远是 block 住的状态)。各种 event listener 所定义 event-handler method 都是执行在 event-dispatching thread,所以当事件发生了,你在 handler method 要作更新 UI 的动作,不需要使用上述提到 method。
我认为在使用 invokeAndWait () 要比较注意的是 Dead lock 的问题. 而是否可以在 "event-dispatching" thread 中作呼叫的问题, jvm 会帮你作检查:
节录自:http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html#invokeAndWait
...
You can safely call invokeLater from any thread,
but invokeAndWait throws an exception if it's called from the event-dispatching thread.
...
所谓 Dead Lock 的情况可以用下来面的例子来概略说明:
你的 Thread 先 lock 一个 resource A, 在未释放该 resource 的前题下,
你将后续的工作透过 invokeAndWait() 交由 event-dispatching thread 来执行,
在 event-dispatching 执行你所交付的工作中, 有一个动作是去 lock resource A,
但是 你的 Tread 已经先 lock resource A, 在 event-dispaching thread
执行完毕你所交付的工作前, 你的 tread 是取不到控制权来将该 resource A
释放的动作, 而 event-dispathing thread 在取不到 resource A 的 lock 是
不可能完成你所交付的动作. 这就是 dead lock....
Duncan 又听见妳酸甜甜的声音 版主 于 2004-02-18 00:12
--------------------------------------------------------------------------------
brianlin wrote:
我认为在使用 invokeAndWait () 要比较注意的是 Dead lock 的问题. 而是否可以在 "event-dispatching" thread 中作呼叫的问题, jvm 会帮你作检查:
节录自:http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html#invokeAndWait
...
You can safely call invokeLater from any thread,
but invokeAndWait throws an exception if it's called from the event-dispatching thread.
我知道会丢出 exception,but exception handling 的成本比较高,应该要尽量避免。你引述的那句子的前两个句子是不是告诉你应该(可以)检查 code 是不是执行在 event-dispatching thread。
If you aren't sure whether your code is executing in an event listener, then you shouldanalyze your program's code and document which thread each method is (and can be) called from. Failing that, you can use the SwingUtilities.isEventDispatchThread() method, which returns true if your code is executing in the event-dispatching thread.
我只是提醒一下,像 event-handler 这种很明显是在 event-dispatching thread 执行的,就不必考虑使用 invokeLater/invokeAndWait。
话说回来,你提到的 dead-lock 的确是很重要的一点,很多人可能会忽略。
weaker 小屁屁~ 于 2004-02-18 00:58
--------------------------------------------------------------------------------
Duncan wrote:
我知道会丢出 exception,but exception handling 的成本比较高,应该要尽量避免。你引述的那句子的前两个句子是不是告诉你应该(可以)检查 code 是不是执行在 event-dispatching thread。
If you aren't sure whether your code is executing in an event listener, then you shouldanalyze your program's code and document which thread each method is (and can be) called from. Failing that, you can use the SwingUtilities.isEventDispatchThread() method, which returns true if your code is executing in the event-dispatching thread.
我只是提醒一下,像 event-handler 这种很明显是在 event-dispatching thread 执行的,就不必考虑使用 invokeLater/invokeAndWait。
话说回来,你提到的 dead-lock 的确是很重要的一点,很多人可能会忽略。
这样我又有一个疑问了
之前我问的问题,当我使用 time-consuming 的 task 时
JTextArea 会无法更新其 UI
因此 Duncan 大说可以使用 new Thread() 来解决
那么我也可以使用 invokeLater 吗?
而 new Thread() 出来跟 event-dispatching thread 又有何不同呢?
Duncan 又听见妳酸甜甜的声音 版主 于 2004-02-18 02:22
--------------------------------------------------------------------------------
weaker wrote:
这样我又有一个疑问了
之前我问的问题,当我使用 time-consuming 的 task 时
JTextArea 会无法更新其 UI
因此 Duncan 大说可以使用 new Thread() 来解决
那么我也可以使用 invokeLater 吗?
而 new Thread() 出来跟 event-dispatching thread 又有何不同呢?
我在这个 Thread 中发表的内容,其意思是说你可以在 event-handler(在 event listener 所定义的 callback function)里改变 UI 组件的状态(不是马上可以见到 visual 上的改变l),callback 执行结束之后,让 event-dispatching thread 继续处理下去,你可以看到改变,把改变 UI 的动作透过 invokeLater/invokeAndWait 来 queue 到 event-dispatching thread 是多余的(本来就是在 event-dispatching thread)。
先前你的那个例子是,你在 event-handler 里改变 UI 组件(JTextArea)的状态本来是可以的,但是你又在 event-handler 里作网络联机的动作 block 住 event-dispatching thread,此 thread 没有继续执行下去你就不会看到视觉上的改变(你再多用几个 repaint 也没用),情况是许多改变 UI 状态的动作堆积在 event-dispatching thread(你设定两次 JTextArea 的 text property),等到网络联机完毕 event-dispatching thread 动了起来,突然之间一下子就更新到最后的状态了,你没看到过程,你只看到最后的状态(许多同样的动作堆在一起,还可能会被合并只作一次)。
我建议你使用另一个 thread 来作网络联机数据传输是因为 JTextArea 的 setText method 是 thread-safe(大部分的 swing 操作都不是,JTextComponent API doc 的 setText method 部分有强调这一点),于是你可以不必考虑多绪时 UI 同步的问题,否则你就应该使用 invokeLater/invokeAndWait 来安插变更 UI 状态的动作到 event-dispatching thread;使用另外一个 thread 来作耗时的工作就不会牵制 event-dispatching thread 的执行,不会影响画面的绘图动作, user 就可以实时看到 JTextArea 上信息的显示。记得,建议你使用多绪是因为 setText 是 thread-safe,所以事情变的简单。
Duncan 又听见妳酸甜甜的声音 版主 于 2004-02-18 02:30
--------------------------------------------------------------------------------
weaker wrote:
这样我又有一个疑问了
之前我问的问题,当我使用 time-consuming 的 task 时
JTextArea 会无法更新其 UI
因此 Duncan 大说可以使用 new Thread() 来解决
那么我也可以使用 invokeLater 吗?
使用 invokeLater 把动作安插到 event-dispatching thread,那还是要等网络联机/数据传完才会在 event-dispatching thread 中处理,那时一样是几乎连续的两个改变 JTextArea text 的动作接着处理,你还是只看到最后显示的信息。
你要记得,并不是执行过 setText 改变 JTextComponent 组件在外观上就是已经改变"完成",其实绘制改变过后的外观都是 queue 在 event-dispatching thread 里,如果 event-dispatching thread 没有持续地处理(执行) queue 当中的动作,你就不能实时看到改变后的外观。
weaker 小屁屁~ 于 2004-02-18 08:38
--------------------------------------------------------------------------------
Duncan wrote:
使用 invokeLater 把动作安插到 event-dispatching thread,那还是要等网络联机/数据传完才会在 event-dispatching thread 中处理,那时一样是几乎连续的两个改变 JTextArea text 的动作接着处理,你还是只看到最后显示的信息。
你要记得,并不是执行过 setText 改变 JTextComponent 组件在外观上就是已经改变"完成",其实绘制改变过后的外观都是 queue 在 event-dispatching thread 里,如果 event-dispatching thread 没有持续地处理(执行) queue 当中的动作,你就不能实时看到改变后的外观。
我大概了解了,谢谢 Duncan 大的耐心解说..
brianlin 于 2004-02-18 10:22
--------------------------------------------------------------------------------
提到 event-dispatching thread , 我想再补充一些, 在 http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html
有建议任何让 event-dispatching thread 所执行的工作都应是可以快速执行完毕,
其理由就如 Duncan 所描述的: 在 event-dispatching thread 一次只执行一个交付给该
event-dispatching thread 的任务, 在该任务执行完之前, event-dispatching 是不能
执行下一个任务.
所以当你交付一个 time-consuming 的任务给 event-dispatching 的话, 假设该任务
需要执行 10 分钟, 则在该 10 分钟内, 所有的 Swing Comp 皆无法重绘, 所有的 JButton
也无法反应相对应动作.
但是我们有时会对一个 JButton 交付一个较为繁重的工作, 如 "Refresh" JButton,
当 user 按下该键后, AP 会建立一个对数据库的联机, 透过 SQL 撷取大量的数据,
根据所取得资料更新 Swing Comp (如 JTable) 的状态, 像这类型的工作我们无法预期
它可以在 1~2 秒结束, 而在该 tutorial 中, 他则是建议将该工作放在另一个 Thread 中
或者交由他提供的 SwingWorker Class
http://java.sun.com/docs/books/tutorial/uiswing/misc/threads.html#SwingWorker
来执行
而另一个和 event-dispatcing Thread 有关的就是
java.util.Timer 和 javax.swing.Timer 的差别了
javax.swing.Timer 会把你所交付的任务交由 event-dispatcing 来执行
而 java.util.Timer 则会另外建立一个 Thread 来执行你所交付的任务.
所以当你需要定期更新 Swing Comp 你应该采用 javax.swing.Timer
而当你撰写 Server AP 需要定时检查某些状态时, 你应该采用 java.util.Timer
Tags: SWT-Designer-研究学习
原创文章如转载,请注明:转载自:飞扬部落编程仓库 : http://www.busfly.net/csdn/
本文链接地址:http://www.busfly.net/csdn/post/SWT-Designer-invokeAndWait-invokeLater.html
如果你喜欢本文,请顶一下,支持我,你的支持是我继续发好文章的最大动力。谢谢。
好东西需要分享,快把本文发给你的朋友吧~!~