最近调试程序时发现,点击某个界面时会出现卡死的情况,出现的频率还是比较频繁的。

再次出现卡死的情况后,利用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方法进行派发。

Swing EDT引起的客户端卡死的更多相关文章

  1. 《FilthyRichClients》读书笔记(一)-SwingのEDT

    <FilthyRichClients>读完了前几个章节,现将我的体会结合工作以来从事Swing桌面开发的经验,对本书的一些重要概念进行一次 分析,对书中的一些遗漏与模糊的地方及时补充,同时 ...

  2. Rsync客户端卡死的问题查询

    简介 某备份系统大量使用rsync来传输文件,但是偶尔会出现rsync客户端在上传数据的时候长时间卡死,本文记录了解决问题的步骤. 本文只涉及rsync客户端中IO相关逻辑,关于rsync的发送算法并 ...

  3. Swing中耗时任务需要另起新线程,这个新线程中更新GUI的操作仍需由EDT来做(转)

    最近调试程序时发现,点击某个界面时会出现卡死的情况,出现的频率还是比较频繁的. 再次出现卡死的情况后,利用jvisualvm查看线程的运行情况,dump操作之后发现线程间出现了死锁:Found one ...

  4. Java客户端工具选择:HTML?Swing?XML?

    整理下面的文章是因为个人觉得写的很好,关于java的客户端了解也并不是太多.看了下面的文章觉得很有必要贴出来,方便自己以后了解java客户端编程. Java软件设计师和管理人员经常会面临这样的难题:在 ...

  5. Swing中的线程并发处理

    理论解释见官方的文档: https://docs.oracle.com/javase/tutorial/uiswing/concurrency/index.html 一个Swing程序中一般有下面三种 ...

  6. 10个使用Java最广泛的现实领域

    10个使用Java最广泛的现实领域 如果你是一个初学者,刚刚开始学习Java,你可能会想Java有什么用呢?除了Minecraft貌似也看不到其他用Java写的游戏,像Adobe Acrobat和Mi ...

  7. Unity3D手游开发实践

    <腾讯桌球:客户端总结> 本次分享总结,起源于腾讯桌球项目,但是不仅仅限于项目本身.虽然基于Unity3D,很多东西同样适用于Cocos.本文从以下10大点进行阐述: 架构设计 原生插件/ ...

  8. 原生JS的Ajax技术

    1.同步和异步 同步现象:客户端发送请求到服务器端,当服务器返回响应之前,客户端都处于等待  卡死状态 异步现象:客户端发送请求到服务器端,无论服务器是否返回响应,客户端都可以随意做其他事情,不会被卡 ...

  9. NFS及RPC讲解

    导读 NFS(Network File System)即网络文件系统,由Sun公司开发,于1984年向外公布.功能是通过网络让不同的机器.不同的操作系统能够彼此分享个别的数据,让应用程序在客户端通过网 ...

随机推荐

  1. ThinkPHP基础知识

    1.入口文件中定义的内容 // 检测PHP环境if(version_compare(PHP_VERSION,'5.3.0','<')) die('require PHP > 5.3.0 ! ...

  2. ceph -s集群报错too many PGs per OSD

    背景 集群状态报错,如下: # ceph -s cluster 1d64ac80-21be-430e-98a8-b4d8aeb18560 health HEALTH_WARN <-- 报错的地方 ...

  3. VIM 文件搜索与替换

    文件内搜索与替换 :[range]s/pattern/string/[c,e,g,i] 例如: :%s/oldword/newword/cg //对文本中全部匹配进行替换 :m,ns/oldword/ ...

  4. destoon_笔记

    {mb_substr($shop_type[catname],0,4)} {dsubstr($v['company'],18)} =================================== ...

  5. 【翻译】A Next-Generation Smart Contract and Decentralized Application Platform

    原文链接:https://github.com/ethereum/wiki/wiki/White-Paper 当中本聪在2009年1月启动比特币区块链时,他同时向世界引入了两种未经测试的革命性的新概念 ...

  6. android 基础02 - Activity 的生命周期及状态

    返回栈 Android 中的 Activity 是可以层叠的,当我们启动一个新的 Activity 时,就会覆盖在原有的 Activity 之上, 点击 Back 会销毁当前 Activity,下面的 ...

  7. JavaScript获取当前url根目录(路径)

    jsp: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&q ...

  8. [one day one question] Vue数组变更不能触发刷新

    问题描述:Vue数组变更不能触发刷新,特别是数组的每个元素都是对象的时候,对象中某个属性的值发生变化,根本无法触发Vue的dom刷新,这怎么破? 解决方案:this.$set(array, index ...

  9. linux 保留内核中sas驱动的加载导致crash问题

    [root@localhost ~]# uname -a Linux localhost.localdomain -.el7.x86_64 问题描述,在crash的时候,小内核因为分配中断号失败而触发 ...

  10. PID算法笔记2

    总所周知,PID算法是个很经典的东西.而做自平衡小车,飞行器PID是一个必须翻过的坎.因此本节我们来好好讲解一下PID,根据我在学习中的体会,力求通俗易懂.并举出PID的形象例子来帮助理解PID.一. ...