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 static
EventQueue.invokeLater(new Runnable() { public 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 /********************************************************* * 非安全操作(1) * * 点击 Run 按钮后,该按钮不会弹起,进度条也不会增加,即 * 直到 10 秒后,Run 按钮弹起,进度条直接跳到满格,中间的所有过程都没有被展示 * * 出现这种情况的原因:当为鼠标添加的事件触发后,调用 mouseClicked()方法, * 该方法也是被当前的UI线程所执行的,一旦UI线程中出现了 * 将造成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线程中非安全操作与安全操作的更多相关文章
- Android 关于操作UI线程
在非UI线程里访问 Android UI toolkit—这个在一个worker线程修改了 View .这会导致不可预期的结果,而且还难以调试. 为了修复这个问题,Android提供了几个方法从非UI ...
- Android UI线程和非UI线程
Android UI线程和非UI线程 UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这 ...
- android脚步---如何看log之程序停止运行,和UI线程和非UI线程之间切换
经常运行eclipse时,烧到手机出现,“停止运行”,这时候得通过logcat查log了.一般这种情况属于FATAL EXCEPTION,所以检索FATAL 或者 EXCEPTION,然后往下看几行 ...
- UI线程异常处理方法
当应用程序启动,创建了一个叫“main”的线程,用于管理UI相关,又叫UI线程.其他线程叫工作线程(Work Thread). Single Thread Model 一个组件的创建并不会新建一个线程 ...
- 关于“UI线程”
http://www.cppblog.com/Streamlet/archive/2013/05/05/199999.html 缘起 这是一篇找喷的文章. 由于一些历史原因和人际渊源,周围同事谈论一些 ...
- 为什么在非UI线程中操作UI的改变失不安全的
因为你如果允许在非UI线程更新操作UI的东西,那我再另一个非UI线程也可以更新这个Ui的东西 这样就会有冲突,比如你的线程刚好跑到修改UI这里,我的另一个UI也有可能跑到这里,所以这样导致线程不安全. ...
- 通过使用Web Workers,Web应用程序可以在独立于主线程的后台线程中,运行一个脚本操作。这样做的好处是可以在独立线程中执行费时的处理任务,从而允许主线程(通常是UI线程)不会因此被阻塞/放慢。
Web Workers API - Web API 接口参考 | MDNhttps://developer.mozilla.org/zh-CN/docs/Web/API/Web_Workers_API ...
- Android 操作UI线程的一些方法
我们经常会在后台线程中去做一些耗时的操作,比如去网络取数据.但是当数据取回来,需要显示到页面上的时候,会遇到一些小麻烦,因为我们都知道,android的UI页面是不允许在其他线程直接操作的.下面总结4 ...
- C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它
C# 委托 / 跨线程访问UI / 线程间操作无效: 从不是创建控件“Form1”的线程访问它 网上的代码都比较复杂,还是这个简单 见代码, 简易解决办法: 主窗体代码 using System; ...
随机推荐
- deviceToken的获取(一)
1.获得deviceToken的过程 1>客户端向苹果服务APNS,发送设备的UDID和英语的Bundle Identifier.2>经苹果服务器加密生成一个deviceToken ...
- mysql设置有外键的主键自增及其他
有外键的主键设置自增. ; ALTER TABLE `<table>` MODIFY COLUMN `id` ) NOT NULL AUTO_INCREMENT FIRST; 创建数据库, ...
- php关于<<<的用法
Heredoc技术,在正规的PHP文档中和技术书籍中一般没有详细讲述,只是提到了这是一种Perl风格的字符串输出技术.但是现在的一些论坛程序,和部分文章系统,都巧妙的使用heredoc技术,来部分的实 ...
- hbase shell-ddl(表定义指令)
hbase表定义指令详细解说篇 1. alter, alter_async, alter_status 2. create 3. describe (可以简写成'desc') 显示某张表的结构情况 ...
- django-forms表单验证
django生成登录随机图片验证码:http://www.cnblogs.com/wupeiqi/articles/4786251.html def insert(request): # print( ...
- CDH- 测试mr
cdh的mr样例算法的jar包在 [zc.lee@ip---- hadoop-0.20-mapreduce]$ pwd /opt/cloudera/parcels/CDH--.cdh5./lib/ha ...
- linux开机过程
一.MBR(main boot record)主引导记录 主引导记录位于0盘面,0磁道,0扇区,早期由512个字节组成. 其中446个字节是boot loader程序.Boot Loader是在操作系 ...
- C++的栈
栈,是一种存储受限的线性数据结构,在存储和访问数据的时候只能访问栈的一端.栈类似于一摞盘子,只能拿去最上面的盘子,也只能把盘子放到最上面.由于这种特点,栈是一种后进先出(Last in / First ...
- 分享知识-快乐自己:HBase编程
HBase编程: 一):大数据(hadoop)初始化环境搭建 二):大数据(hadoop)环境搭建 三):运行wordcount案例 四):揭秘HDFS 五):揭秘MapReduce 六):揭秘HBa ...
- php 二维数组验证一个值是否存在
php 判断数字在二维数组里 $arr = array( array('a', 'b'), array('c', 'd') ); in_array('a', $arr); // 此时返回的永远都是 f ...