java 事件分发线程_事件分发线程EDT

Java的事件分发线程(EDT)负责处理所有组件的访问,确保界面组件状态同步,避免线程同步复杂性。但长时间任务可能导致EDT阻塞,造成界面无响应。解决方案是使用异步线程处理任务,并通过SwingUtilities.invokeLater等方法在EDT上更新界面。
摘要由CSDN通过智能技术生成

所有的事件处理都在Event Dispatch Thread(EDT)上进行,此一类事件模型通常叫做单线程模型。

这种模型规定所有对组件的访问操作必须在EDT 上完成。

为什么对于组件的访问需要在EDT 上完成?这主要是为了保证对于组件状态的改变是同步的,保证了界面组件的可确定性。这种模型是大部分图形用户界面工具采用的模型,包括Swing/AWT、SWT、GTK、WinForm 等等.

?

这种模型的好处是,结构设计和代码实现都比较简单,避免了为了实现线程同步的复杂处理。

但是也带来了一些问题,最常见的问题是,程序员容易将长时间复杂任务的处理放在事件处理函数完成,造成EDT 线程被阻塞,给用户造成界面失去响应的错觉。

?

其实人们对于Swing 速度慢和反映迟钝的感觉大部分来源于此,简单的说,是程序员的问题,而不是Swing 自身的问题,是因为程序员没有理解这种事件处理机制造成的。

其实在SWT、GTK、WinForm 等任何以这种事件模型为基础的工具都会出现。

重现的方法就是你简单的将长时间处理的任务放在事件处理函数中,你的用户界面就会失去响应。

如何解决这种问题?

通用的办法就是采用异步线程处理长时间任务。

但是还要记住的是,在这种任务中对于界面的更新要采用SwingUtilities.invokeLater 或者在SWT 采用Synchronize 方法,将访问操作放到EDT 上进行。

?

?示例

380424b681e0c68d34701a5078ac9a72.png

?

?示例代码

class="java">package test;

import java.awt.BorderLayout;

import java.awt.EventQueue;

import javax.swing.JFrame;

import javax.swing.JLabel;

import javax.swing.JPanel;

import javax.swing.SwingUtilities;

import javax.swing.border.EmptyBorder;

import javax.swing.JButton;

import java.awt.event.ActionListener;

import java.awt.event.ActionEvent;

public class Frame1 extends JFrame {

private static final long serialVersionUID = 1L;

private JPanel contentPane;

/**

* Launch the application.

*/

public static void main(String[] args) {

EventQueue.invokeLater(new Runnable() {

public void run() {

try {

Frame1 frame = new Frame1();

frame.setVisible(true);

} catch (Exception e) {

e.printStackTrace();

}

}

});

}

/**

* Create the frame.

*/

public Frame1() {

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

setBounds(100, 100, 450, 300);

contentPane = new JPanel();

contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));

contentPane.setLayout(new BorderLayout(0, 0));

setContentPane(contentPane);

final JLabel label = new JLabel();

contentPane.add(label, BorderLayout.CENTER);

JButton btnNewButton = new JButton("按钮");

contentPane.add(btnNewButton, BorderLayout.SOUTH);

btnNewButton.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

label.setText("开始执行...");

//耗时操作,新启线程去处理,但是外观的改变,仍需要放到EDT去执行。

Thread thread = new Thread() {

@Override

public void run() {

try {

//更新外观

SwingUtilities.invokeLater(new Runnable(){

public void run() {

label.setText("正在执行耗时任务...");

}

});

// 模拟耗时操作

Thread.sleep(5*1000);

//更新外观

SwingUtilities.invokeLater(new Runnable(){

public void run() {

label.setText("耗时任务执行完毕");

}

});

} catch (Exception e2) {

e2.printStackTrace();

}

}

};

thread.start();

}

});

}

}

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

d987efb2059a150df429c1a2bfb331d3.png

大小: 3.3 KB

查看图片附件

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值