测试代码如下:

1、耗时计算没有单独起线程处理,耗时计算在EDT线程执行,导致界面没有响应,处于卡死状态

package thread;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Test {
	
	
	public static void main(String[] args) {
		JFrame frame=new JFrame();
		final JButton button=new JButton();
		button.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				button.setLabel("busy");
				button.setEnabled(false);
//				ExecutorService executorService=Executors.newCachedThreadPool();
//				executorService.execute(new Runnable() {
//					
//					public void run() {
						// TODO Auto-generated method stub
						for (int i = 0; i < 10000000; i++) {
							System.out.println("operation is running");
						}
//						button.setLabel("");
//					}
//				});
		
				
			}
		});
		button.setSize(50, 20);
		frame.add(button);
		frame.setVisible(true);
		frame.pack();
	}

}

 

 

2、

java测试并发方法 java测试并发量_string

 

2、起线程处理耗时操作,耗时操作单独在一个线程处理,界面及时响应,没有问题

java测试并发方法 java测试并发量_java测试并发方法_02

3、窗体设置部分代码在主线程处理

java测试并发方法 java测试并发量_button_03

 4、建议代码如下,对界面的操作应该放在edt线程里去处理,即使是组件的初始化也最好放在EDT中处理,虽然从主线成直接初始化组件发生的错误概率很小,但还是要避免。

上述的SwingUtilites.invokeLater也可有EventQueue.invokeLater代替,这两个方法都是正确的,选择任何一个都可以。实际上,SwingUtilities版只是一个薄薄的封装方法,它直接调用 EventQueue.invokeLater。因为Swing框架本身经常调用SwingUtilities,使用SwingUtilities可以减 少程序引入的类。

第一条规则同通常称为单一线程规则,在任何非EDT线程中都不该接触swing组件。这两条规则看似是矛盾的,既然将耗时的操作放入其他其他线程,那么当耗时操作完成时如何将结果更新到swing组件当中去?因为不能在其他线程中接触swing组件的。其实想想也不难,既然EDT本质上是从事件队列中拿出事件来处理的,那么只要能在其他线程中把耗时操作完成以后再把更细ui组件的代码封装放到事件队列中就行了,到时EDT自然会从事件队列取出代码执行用以达到更新的目的,这样两条规则都满足了。其实在任何线程中,可以使用两种方法想事件队列添加任意的动作。即调用SwingUtilites类(或者EventQueue类也是一样)invokeLater或者invokeAndWait两个静态方法向事件队列添加任务。

 

package thread;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;

public class Test {
	
	
	public static void main(String[] args) {
		JFrame frame=new JFrame();
		final JButton button=new JButton();
		button.addActionListener(new ActionListener() {
			
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				button.setLabel("busy");
				button.setEnabled(false);
				ExecutorService executorService=Executors.newCachedThreadPool();
				executorService.execute(new Runnable() {
					
					public void run() {
						// TODO Auto-generated method stub
						for (int i = 0; i < 10000000; i++) {
							System.out.println("operation is running");
						}
						//对gui组建的操作放在edt线程处理
						SwingUtilities.invokeLater(new Runnable() {
							
							public void run() {
								// TODO Auto-generated method stub
								button.setLabel("");
							}
						});
					}
				});
		
				
			}
		});
		//界面的初始化其实也不应该放在主线程执行,应该放在edt线程,虽然出错的概率不大
		button.setSize(50, 20);
		frame.add(button);
		frame.setVisible(true);
		frame.pack();
	}

}