Java Swing多线程死锁问题解析

原创
开发 后端
Java Swing是Java核心技术之一,通过改技术构造出的图形界面非常美观强大。但是在进行复杂开发,特别是多线程开发,则需要解决一些特殊问题。

【51CTO独家特稿】在基于Java Swing进行图形界面开发的时候,经常遇到的就是Swing多线程问题。我们可以想想一下,如果需要在一个图形界面上显示很多数据,这些数据是经过长时间、复杂的查询和运算得到的。如果在图形界面的同一个线程中进行查询和运算工作则会导致一段时间界面处于死机状态,这会给用户带来不良的互动感受。为了解决这个问题,一般会单独启动一个线程进行运算和查询工作,并随时更新图形界面。这时候,另一个问题就出现了,可能不仅没有解决原来偶尔死机问题,还可能导致程序彻底死掉。幸运的是在JDK中暗藏了一个中断程序的快捷键,就是CTRL+BREAK,这个快捷键Sun并没有在文档中公布。如果在命令行模式下启动Java程序,然后按CTRL+BREAK键,会得到堆栈的跟踪信息。从这些跟踪信息中就可以知道具体引发死机的位置了。

当一个程序产生死锁的时候,你一定会希望尽快找到原因并且解决它。这时候,你一般的精力会用在查找引发死锁的位置,另一半的精力会用于对堆栈进行跟踪一确定引发死锁的原因。但是在Java Swing程序中,你的所有努力可能都是没有价值的。这是因为Java对Swing的多线程编程有一个特殊要求。就是在Swing里,只能在与Swing相同的线程里对GUI元件进行修改。

也就是说,如果你要执行类似于jLabel1.setText("blabla")代码,必须在Swing线程中,而不允许在其他线程当中。如果必须在其他线程中修改元件,可以使用类似一下方式解决:

  1. SwingUtilities.invokeLater(new Runnable() {  
  2.     public void run() {  
  3.         jLabel1.setText("blabla");  
  4.     }  

invokeLater方法虽然表面有时间延迟执行含义,但是实际上几乎没有任何影响,可能在几毫秒之内就会被执行。另外还有一个invokeAndWait方法,除非特殊需要,否则几乎是不用的。

在不使用invokeLater的情况下,导致刷新问题是可以理解的,但是导致死锁就优点令人匪夷所思了。幸运的是,不是任何时候都需要调用改方法,这是因为大多数情况下,我们都是在与Swing同一个线程里进行界面更新。例如监听按钮点击事件的ActionListener.actionPerformed方法就是运行在与Swing相同的线程中的。但是如果在回调类中引用了另一个类,并且是不属于AWT/Swing的,那么结果就很难确定了。所以说使用invokeLater应该是最安全的。

需要注意的是,在invokeLater做的任何事情,都会导致Swing线程窗口绘制工作暂停下来,等候invokeLater工作结束。所以不要在invokeLater进行耗时操作,尽量只执行那些界面绘制相关的工作。可以通过代码重构,将那些与界面更新相关的代码集中起来统一处理。

一个建议是那些在Swing中使用的类进行合理的设计。代码执行前判断是否处于Swing线程当中(使用SwingUtilities.isEventDispatchThread()方法),如果不是,则需要通过SwingUtilities.invokeLater(Runnable)执行,否则则直接执行代码。但是这说起来简单,但是实际操作会遇到很多困难。

【编辑推荐】

  1. 有趣的Java对象序列化缓存问题
  2. 关于Java对象序列化您不知道的5件事
  3. Java 7 I/O新功能探秘:同步操作,多播与随机存取
  4. Java实用技巧:当不能抛出checked异常时
  5. 多线程开发的捷径:构建Java并发模型框架
责任编辑:佚名 来源: 51CTO
相关推荐

2020-08-13 08:45:09

多线程死锁

2011-06-02 17:27:49

iphone 多线程

2009-08-27 13:55:08

C#子线程

2017-01-19 10:24:38

Java多线程问题

2015-12-22 10:39:52

Java多线程问题

2010-03-16 19:29:26

Java多线程操作

2013-05-29 10:47:50

Android开发Java多线程java面试题

2012-01-17 16:41:08

JavaSwing

2021-03-28 09:12:58

多线程死锁技术热点

2011-04-18 09:22:38

多线程

2010-02-01 17:25:09

Python多线程

2011-06-22 13:47:16

Java多线程

2011-06-22 13:57:54

Java多线程

2009-03-18 09:26:23

Winform多线程C#

2009-03-12 10:52:43

Java线程多线程

2019-09-26 10:19:27

设计电脑Java

2012-07-24 17:10:10

Linux操作系统

2010-04-29 12:42:09

Unix系统

2010-03-16 18:40:59

Java多线程编程

2021-03-05 07:38:52

C++线程编程开发技术
点赞
收藏

51CTO技术栈公众号