------------------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 static
void main(String[] args) {

 

EventQueue.invokeLater(new Runnable() {

public
void 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

public
void 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线程中可以非常安全操作任何元素的属性

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

*/

 

//(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】

UI线程中非安全操作与安全操作的更多相关文章

  1. Android 关于操作UI线程

    在非UI线程里访问 Android UI toolkit—这个在一个worker线程修改了 View .这会导致不可预期的结果,而且还难以调试. 为了修复这个问题,Android提供了几个方法从非UI ...

  2. Android UI线程和非UI线程

    Android UI线程和非UI线程 UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这 ...

  3. android脚步---如何看log之程序停止运行,和UI线程和非UI线程之间切换

    经常运行eclipse时,烧到手机出现,“停止运行”,这时候得通过logcat查log了.一般这种情况属于FATAL EXCEPTION,所以检索FATAL 或者 EXCEPTION,然后往下看几行 ...

  4. UI线程异常处理方法

    当应用程序启动,创建了一个叫“main”的线程,用于管理UI相关,又叫UI线程.其他线程叫工作线程(Work Thread). Single Thread Model 一个组件的创建并不会新建一个线程 ...

  5. 关于“UI线程”

    http://www.cppblog.com/Streamlet/archive/2013/05/05/199999.html 缘起 这是一篇找喷的文章. 由于一些历史原因和人际渊源,周围同事谈论一些 ...

  6. 为什么在非UI线程中操作UI的改变失不安全的

    因为你如果允许在非UI线程更新操作UI的东西,那我再另一个非UI线程也可以更新这个Ui的东西 这样就会有冲突,比如你的线程刚好跑到修改UI这里,我的另一个UI也有可能跑到这里,所以这样导致线程不安全. ...

  7. 通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。

    Web Workers API - Web API 接口参考 | MDNhttps://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API ...

  8. Android 操作UI线程的一些方法

    我们经常会在后台线程中去做一些耗时的操作,比如去网络取数据.但是当数据取回来,需要显示到页面上的时候,会遇到一些小麻烦,因为我们都知道,android的UI页面是不允许在其他线程直接操作的.下面总结4 ...

  9. C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它

    C# 委托 / 跨线程访问UI /  线程间操作无效: 从不是创建控件“Form1”的线程访问它 网上的代码都比较复杂,还是这个简单 见代码, 简易解决办法: 主窗体代码 using System; ...

随机推荐

  1. Flex中容器的完全隐藏

    在html中,但我们设置某个dom元素的display属性为none时,dom元素不可见且其占用空间从dom树上隐藏,而在Flex中,但我们把某个组件的visible属性visible设为false的 ...

  2. VHDL基础 学习笔记

    最近一直忙着学校里的活动,所以没怎么更新,上周活动忙完了,正好也借着数电实验的机会,重新学习一下VHDL的编程.以下是转自360doc的教程: ———————————————————————————— ...

  3. Data Structure Array: Given an array of of size n and a number k, find all elements that appear more than n/k times

    http://www.geeksforgeeks.org/given-an-array-of-of-size-n-finds-all-the-elements-that-appear-more-tha ...

  4. inline-block元素的4px空白间距解决方案

    http://www.jb51.net/css/68785.html  inline-block元素的4px空白间距解决方案 

  5. 希尔排序(Shell Sort)

    一.思路 希尔排序是基于插入排序算法,通过允许不相邻的元素进行交换这一简单的改进,使数组变为局部有序,最终再用插入排序. 希尔排序的思想是使数组中任意间隔h的元素都是有序的.这样的数组被称为h有序数组 ...

  6. SpringCloud-断路器(Hystrix)

    在微服务架构中,根据业务来拆分成一个个的服务,服务与服务之间可以相互调用(RPC),在Spring Cloud可以用Rest Template + Ribbon和Feign来调用.为了保证其高可用,单 ...

  7. Mac安装使用kettle

    kettle是一个ETL工具 下载安装 https://jaist.dl.sourceforge.net/project/pentaho/Data Integration/ 选择版本后下载,并解压,如 ...

  8. 带SoapHeader验证的WebServices

    一般在项目中,制作的都是基于SOAP协议的webservices,其描述语言是WSDL.但是有时候在项目中,需要保证webservices的安全,需要对其进行进行验证,那么我们就要实现SoapHead ...

  9. HTTP-接触

    [HTTP]http是基于TCP/IP协议的应用层协议,他不涉及数据包(packet)传输,主要规定了客户端和服务器之间的通信格式,默认端口是80端口. 不同版本http协议里的相关概念[Conten ...

  10. mysql多位小数字段用decimal类型

    转自http://database.51cto.com/art/201005/201651.htm