Board logo

标题: Java Swing多线程死锁问题解析 [打印本页]

作者: qingqing3721    时间: 2011-7-29 19:25     标题: Java Swing多线程死锁问题解析

在基于Java
Swing进行图形界面开发的时候,常常遇到的就是Swing多线程成绩。我们可以想想一下,假设需求在一个图形界面上显示很多数据,这些数据是经过长时
间、复杂的查询和运算失掉的。假设在图形界面的同一个线程中进行查询和运算工作则会招致一段工夫界面处于死机形态,这会给用户带来不良的互动感受。为了解
决这个成绩,普通会单独启动一个线程进行运算和查询工作,并随时更新图形界面。这时候,另一个成绩就出现了,可能不只没有处置原来偶然死机成绩,还可能导
致程序彻底死掉。幸运的是在JDK中暗藏了一个中断程序的快捷键,就是CTRL+BREAK,这个快捷键Sun并没有在文档中公布。假设在命令行模式下启
动Java程序,然后按CTRL+BREAK键,会失掉堆栈的跟踪信息。从这些跟踪信息中就可以晓得具体引发死机的位置了。  当一个程序
发生死锁的时候,你一定会希望尽快找到原因并且处置它。这时候,你普通的精力会用在查找引发死锁的位置,另一半的精力会用于对堆栈进行跟踪一确定引发死锁
的原因。但是在Java
Swing程序中,你的所有努力可能都是没有价值的。这是因为Java对Swing的多线程编程有一个特殊要求。就是在Swing里,只能在与Swing
相反的线程里对GUI元件进行修改。  也就是说,假设你要执行类似于jLabel1.setText("blabla")代码,必须在
Swing线程中,而不允许在其他线程当中。假设必须在其他线程中修改元件,可以运用类似一下方式处置:

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

 invokeLater方法虽然表面有工夫延迟执行含义,但是实际上几乎没有任何影响,可能在几毫秒之内就会被执行。另外还有一个
invokeAndWait方法,除非特殊需求,否则几乎是不用的。  在不运用invokeLater的情况下,招致刷新成绩是可以了解
的,但是招致死锁就优点令人匪夷所思了。幸运的是,不是任何时候都需求调用改方法,这是因为大多数情况下,我们都是在与Swing同一个线程里进行界面更
新。例如监听按钮点击事情的ActionListener.actionPerformed方法就是运行在与Swing相反的线程中的。但是假设在回调类
中援用了另一个类,并且是不属于AWT/Swing的,那么后果就很难确定了。所以说运用invokeLater应该是最安全的。  需求
留意的是,在invokeLater做的任何事情,都会招致Swing线程窗口绘制工作暂停下来,等候invokeLater工作完毕。所以不要在
invokeLater进行耗时操作,尽量只执行那些界面绘制相关的工作。长生鸟可以经过代码重构,将那些与界面更新相关的代码集中起来统一处置。 
 一个建议是那些在Swing中运用的类进行合理的设计。代码执行前判别能否处于Swing线程当中(运用
SwingUtilities.isEventDispatchThread()方法),假设不是,则需求经过
SwingUtilities.invokeLater(Runnable)执行,否则则直接执行代码。但是这说起来复杂,但是实际操作会遇到很多困难。




欢迎光临 编程开发论坛 (http://bbs.lihuasoft.net/) Powered by Discuz! 6.0.0