SwingUtilities.invokeLater 解决DR project的bug:多线程下swing组件不稳定

SwingUtilities.invokeLater

SwingUtilities.invokeLater(new Runnable() {

           public void run() {

           textControl.append(String.valueOf((char)b));

           }

});

---------

This makes the following line of code:

       textControl.append(String.valueOf((char)b));

to be executed not on the current thread, but on the Event Dispatch Thread (EDT). If you tried to execute it on your current thread, it would result in undefined behavior because Swing is not thread-safe and all GUI operations must happen on the mentioned EDT.

That simply adds a task to the tasks queue of the Java thread which is in charge of the rendering & events for your whole application.

Swing works on Single Threaded Model. All the updates to the UI related things should be done through Event Dispatch Thread.

以下摘自:https://blog.csdn.net/altermanzhu/article/details/80325320

SwingAPI是非线程安全的,也就是说不能在任意地方调用,它应该只在EDT中调用。Swing的线程安全靠事件队列和EDT来保障。EventQueue的派发机制由单独的一个线程管理,这个线程称为事件派发线程(EDT)。和其他很多桌面API一样,Swing将GUI请求放入一个事件队列中执行。 通过EDT,使得不具备线程安全的Swing函数库避开了并发访问的问题。

因此,任何涉及多线程任务的UI,更新操作要放在主线程,将耗时的业务逻辑另起线程执行,保持主线程不被耗时任务中断即可。

以下摘自:https://blog.csdn.net/bbirdsky/article/details/17048841

Swing提供一组“轻量级”(全部是 Java 语言)组件,尽量让这些组件在所有平台上的工作方式都相同。
是单线程、线程不安全的。
现象1:当点击了开始按钮,画面就卡住了。按钮不能点击,进度条没有被更新,输入框上也没有任何信息。
原因分析:Swing是线程不安全的,是单线程的设计,所以只能从事件派发线程访问将要在屏幕上绘制的Swing组件。ActionListener的actionPerformed方法是在事件派发线程中调用执行的,而点击了开始按钮后,执行了go()方法,在go()里,虽然也去执行了更新组件的方法
EventDispatchThread repaint()也是使用的EventDispatchThread线程来对GUI组件进行更新;
为了让画面不会卡住,我们来修改代码,将耗时的工作放在一个线程里去做
2、invokeAndWait
   与invoikeLater一样,invokeAndWait也把可运行对象排入事件派发线程的队列中,invokeLater在把可运行的对象放入队列后就返回,而invokeAndWait一直等待知道已启动了可运行的run方法才返回。如果一个操作在另外一个操作执行之前必须从一个组件获得信息,则invokeAndWait方法是很有用的。
invokeLater和invoikeAndWait的一个重要区别:可以从事件派发线程中调用invokeLater,却不能从事件派发线程中调用invokeAndWait,从事件派发线程调用invokeAndWait的问题是:invokeAndWait锁定调用它的线程,直到可运行对象从事件派发线程中派发出去并且该可运行的对象的run方法激活,如果从事件派发线程调用invoikeAndWait,则会发生死锁的状况,因为invokeAndWait正在等待事件派发,但是,由于是从事件派发线程中调用invokeAndWait,所以直到invokeAndWait返回后事件才能派发。
  由于Swing是线程不安全的,所以,从事件派发线程之外的线程访问Swing组件是不安全的,SwingUtilities类提供这两种方法用于执行事件派发线程中的代码
总结: GUI中多线调用方法应该使用:SwingUtilities.invokeLater和invokeAndWait 而不是普通情况下那样应用.
是一个危险的操作,运行是不正常的。
解释:SwingUtilities.invokeLater()方法使事件派发线程上的可运行对象排队。当可运行对象排在事件派发队列的队首时,就调用其run方法。其效果是允许事件派发线程调用另一个线程中的任意一个代码块。
还有一个方法SwingUtilities.invokeAndWait()方法,它也可以使事件派发线程上的可运行对象排队。
他们的不同之处在于:SwingUtilities.invokeLater()在把可运行的对象放入队列后就返回,而SwingUtilities.invokeAndWait()一直等待知道已启动了可运行的run方法才返回。如果一个操作在另外一个操作执行之前必须从一个组件获得信息,则应使用SwingUtilities.invokeAndWait()方法。

猜你喜欢

转载自www.cnblogs.com/rySZ/p/10654196.html