事件分发线程EDT_JAVA_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > JAVA > 事件分发线程EDT

事件分发线程EDT

 2017/9/25 18:38:15  huangqiqing123  程序员俱乐部  我要评论(0)
  • 摘要:所有的事件处理都在EventDispatchThread(EDT)上进行,此一类事件模型通常叫做单线程模型。这种模型规定所有对组件的访问操作必须在EDT上完成。为什么对于组件的访问需要在EDT上完成?这主要是为了保证对于组件状态的改变是同步的,保证了界面组件的可确定性。这种模型是大部分图形用户界面工具采用的模型,包括Swing/AWT、SWT、GTK、WinForm等等.这种模型的好处是,结构设计和代码实现都比较简单,避免了为了实现线程同步的复杂处理。但是也带来了一些问题,最常见的问题是
  • 标签:事件 线程

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

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

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

?

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

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

?

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

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

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

如何解决这种问题?

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

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

?

?示例



?

?示例代码

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();
			}
		});
	}
}

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

?

  • 大小: 3.3 KB
  • 查看图片附件
发表评论
用户名: 匿名