Swing中耗时任务需要另起新线程,这个新线程中更新GUI的操作仍需由EDT来做(转)
来源:互联网 发布:js给标签添加style 编辑:程序博客网 时间:2024/06/06 15:01
最近调试程序时发现,点击某个界面时会出现卡死的情况,出现的频率还是比较频繁的。
再次出现卡死的情况后,利用jvisualvm查看线程的运行情况,dump操作之后发现线程间出现了死锁:
Found one Java-level deadlock:
=============================
"Thread-122":
waiting to lock monitor 0x484052e4 (object 0x1af2bb08, a com.raisecom.ems.templet.client.panel.SnmpTablePanel),
which is held by "AWT-EventQueue-0"
"AWT-EventQueue-0":
waiting to lock monitor 0x4861c81c (object 0x180d5950, a java.awt.Component$AWTTreeLock),
which is held by "Thread-122“
再在线程堆栈中查看根源的线程及方法,找到如下的代码:
public void onSelectionChanged(SelectionChangedEvent e) { Object source = e.getSource(); if (source instanceof AbstractMenuTreePanel) { ///单起个线程处理显示 Thread thread = new Thread(){ public void run() { if(!"".equals(DemarcationConfigCenterView.this.m_ProVer)) refreshConfigPanel2(); else refreshConfigPanel(); } } } }; thread.start(); }
EDT以外的线程中更新界面都需要SwingUtilities.invokeLater,修改代码:
public void onSelectionChanged(SelectionChangedEvent e) { Object source = e.getSource(); if (source instanceof AbstractMenuTreePanel) { ///单起个线程处理显示 Thread thread = new Thread(){ public void run() { if(!"".equals(DemarcationConfigCenterView.this.m_ProVer)) SwingUtilities.invokeLater(new Runnable() { public void run() { refreshConfigPanel2(); } }); else{ SwingUtilities.invokeLater(new Runnable() { public void run() { refreshConfigPanel(); } }); } } }; thread.start(); }
测试没有发生客户端卡死的现象了。
当swing界面程序启动的时候,会启动3个进程, 1、主线程 2、系统工具包线程:负责捕获操作系统事件,然后将事件转换成swing的事件,然后发送到事件派发线程EDT 3、事件派发线程(EDT):将事件派发到各个组件,并负责调用绘制方法更新界面
所有的事件,例如键盘,鼠标事件,都会由工具包线程转换成swing事件,然后放到事件队列EventQueue中,而这个EventQueue的派发机制是由EDT来管理的。 所以任何修改组件状态的方法都应该在EDT中执行,包括构造方法。Swing这样的构造原理经常会造成的情况就是,在EDT中执行长时间的事件,使EDT不能及时响应更新界面的事件,就是所说的界面卡住,这种不光是新手就是比较熟练的程序员也会犯的一个错误。所以必须避免在EDT中执行长时间的操作,而避免的方法就是多线程,启动另外的线程来处理冗长的操作,比如操作数据库,读写文件等,在这过程中可能要更新界面来给用户以提示,比如显示一个进度条,过一段事件更新一下界面,但是在EDT以外的线程中更新界面都是无效的,这在前面已经说过,要更新界面就要将对界面的更新操作放到EDT中,但是事件又是在另外的线程中执行的,要解决这个问题就要使用SwingUtilities提供的一个方法了 invokeLater,
public void actionPerformed(ActionEvent e){ new Thread(new Runnable(){ //do something SwingUtilities.invokeLater(new Runnable(){ pulic void run(){ //update the GUI } }); }).start;}
这个方法的作用就是将一个更新界面的任务放到EDT中,EDT会在适当的时候进行调用以更新界面。invokeLater负责创建一个含有Runnable的特定事件,并让其在EDT中排队等待调用,当被调用时就会运行Runnable中的run方法进行派发。
http://www.cnblogs.com/lnlvinso/p/3685863.html
- Swing中耗时任务需要另起新线程,这个新线程中更新GUI的操作仍需由EDT来做(转)
- Android中启动线程来进行耗时操作
- Swing如何正确的处理界面中的线程(EDT)
- 4.5.3 Async耗时操作必须由子线程完成,更新UI需要由主线程完成
- Java Swing中GUI代码的线程同步
- android 直接在activity/broadcast receiver中启动子线程来处理长时间的耗时任务不行吗?
- 深入浅出Swing事件分发线程(EDT线程)
- Android中为什么主线程更新UI,子线程执行耗时操作?
- 禁止在窗口界面线程中进行线程同步或进行耗时的操作。。。
- 浅析Swing线程模型和EDT
- 浅析Swing线程模型和EDT
- 浅析Swing线程模型和EDT
- AsyncTask的套路(线程间通信中处理耗时任务的工具封装类)
- Android中使用Handler和异步任务(AsyncTack)来为UI线程执行费时操作
- swing中线程
- 【Java线程】Swing事件分发线程EDT与SwingUtilities.invokeLater
- Swing GUI线程安全问题
- onReceive中完成一项比较耗时的工作 , 应该启动 Service 来完成 ,不能使用子线程来解决!!!
- java更改jdk的版本号
- random函数用法
- JSON.parse()和JSON.stringify()
- 典型的递归调用程序
- fiddler修改请求上行下行数据
- Swing中耗时任务需要另起新线程,这个新线程中更新GUI的操作仍需由EDT来做(转)
- PHP 页面编码声明方法详解(header或meta,解决中文乱码问题)
- Studing Day2
- nginx
- Hi3531与Hi3520 GPIO口的对比及驱动的修改
- 上线之后客户端自动刷新
- Linux进程通信之共享内存-shmget shmat
- 关于realloc的使用与分析
- java与c通信实现方案