UI线程中非安全操作与安全操作

------------------siwuxie095

  

  

  

  

  

  

  

工程名:SwingUIThreadSafeTest

包名:com.siwuxie095.swinguithread

类名:MyFrame.java

  

  

工程结构目录如下:

 

  

  

  

  

代码:

  

package com.siwuxie095.swinguithread;

  

import java.awt.BorderLayout;

import java.awt.EventQueue;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

  

import javax.swing.JButton;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JProgressBar;

import javax.swing.UIManager;

import javax.swing.UnsupportedLookAndFeelException;

import javax.swing.border.EmptyBorder;

  

import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;

  

//MyFrame 直接继承自 JFrame

public class MyFrame extends JFrame {

  

private JPanel contentPane;

  

/**

* Launch the application.

*/

 

public staticvoid main(String[] args) {

 

EventQueue.invokeLater(new Runnable() {

publicvoid run() {

try {

MyFrame frame = new MyFrame();

frame.setVisible(true);

} catch (Exception e) {

e.printStackTrace();

}

}

});

 

}

  

/**

* Create the frame.

*/

public MyFrame() {

 

try {

UIManager.setLookAndFeel(new WindowsLookAndFeel());

} catch (UnsupportedLookAndFeelException e) {

e.printStackTrace();

}

 

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

 

JProgressBar progressBar = new JProgressBar();

contentPane.add(progressBar, BorderLayout.NORTH);

 

JButton btnRun = new JButton("Run");

 

//为按钮 Run 添加 mouseClicked 事件

btnRun.addMouseListener(new MouseAdapter() {

@Override

publicvoid mouseClicked(MouseEvent e) {

/*********************************************************

* 非安全操作(1)

*

* 点击 Run 按钮后,该按钮不会弹起,进度条也不会增加,即界面卡死,没有任何反应

* 直到 10 秒后,Run 按钮弹起,进度条直接跳到满格,中间的所有过程都没有被展示

*

* 出现这种情况的原因:当为鼠标添加的事件触发后,调用 mouseClicked()方法,

* 该方法也是被当前的UI线程所执行的,一旦UI线程中出现了类似 sleep(1000) 这样的阻塞方法,

* 将造成UI线程一直在阻塞的地方等待,而不会执行任何界面刷新的工作,这就导致了界面卡死的现象

*

* 如果要编写一个响应良好的界面,不能在UI线程中执行非常耗时的操作

* 如:等待、UI的读写、网络的读写

*

* 如果一定要执行等待、或每隔多长时间执行一个特殊的动作,可以使用 Swing Timer 进行操作

* 如果需要读取大量的网络数据,或读写本地文件,可以创建一个新的线程 SwingWorker

*********************************************************

*/

 

// //(1)只需点击一次按钮

// for (int i = 1; i <= 10; i++) {

// try {

// //1 秒进度条增加一格

// //有异常抛出,用 try catch 捕获

// Thread.sleep(1000);

// progressBar.setValue(i*10);

// } catch (InterruptedException e1) {

// e1.printStackTrace();

// }

// }

 

 

/*********************************************************

* 安全操作(2)

*

* 在为界面中的元素添加的监听器(各种事件)触发所产生的回调方法

* 都是由 Swing 的事件派发线程(UI线程)来完成的

*

* UI线程中可以非常安全操作任何元素的属性

* 如:让进度条根据自己的 value 10

*********************************************************

*/

 

//(2)需要连续点击按钮

progressBar.setValue(progressBar.getValue()+10);

 

 

}

});

 

btnRun.setFocusable(false);

contentPane.add(btnRun, BorderLayout.SOUTH);

}

  

}

  

  

  

将窗体JFrame 的 LookAndFeel 设定为 Windows

  

  

在根面板 contentPane 的上方添加一个 JProgressBar,

下方添加一个JButton

  

  

将 JButton 的文本(text)改为 Run,并 Rename 为 btnRun,

将 focusable 属性设为 false

  

  

为 JButton 添加 mouseClicked 事件,当点击 Run 按钮时,进度条的增加

  

  

非安全操作:

  

  

  

运行程序:

点击 Run 按钮后,按钮不会弹起,进度条也不会增加,

界面卡死。直到 10 秒后,Run 按钮才弹起,进度条

直接跳到满格

  

  

  

界面卡死的原因:

  

当为鼠标添加的事件触发后,调用 mouseClicked()方法,

该方法也是被当前的UI线程所执行的

  

一旦UI线程中出现类似 Thread.sleep(1000); 这样的阻塞方法,将

造成UI线程一直在阻塞处 Thread.sleep(1000);等待 ,而不会执行

任何界面刷新的工作,进而导致界面卡死

  

  

  

安全操作:

  

  

  

运行程序:

  

  

  

  

  

  

因界面中元素的监听器(各种事件)触发所产生的回调方法都是

由 Swing 的事件派发线程(UI线程)来完成的

  

「事件派发线程Event Dispatch Thread,简称 EDT」

  

所以,如果要编写一个响应良好的界面,不能在UI线程中执行非常耗时的操作

  

如:等待、文件的读写、网络数据的读写

  

 

如果一定要执行等待、或每隔一定时间执行一个特殊的动作,可以

使用 Swing 的 Timer 进行操作

  

  

如果需要读取大量的网络数据,或读写本地文件,可以

使用Swing 的 SwingWorker 进行操作

  

  

  

  

  

  

  

  

【made by siwuxie095】

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值