为什么80%的码农都做不了架构师?>>>   

要理解UI线程,先要了解一下“消息循环”这个概念。链接是百度百科上的条目,简单地说,操作系统把用户界面上的每个操作都转化成为对应的消息,加入消息队列。然后把消息转发给对应的应用程序(一般来说,就是活动窗口),应用程序根据自己的逻辑处理这些消息。 如果应用程序处理某个消息事件的时候,用了很长的时间,这时候后续的消息无法及时得到处理,就会造成应用程序没有响应,也就是常说的“假死”状态。 所以,应用程序如果处理某个事件需要较长的时间,需要把这个操作放到一个另外的线程中进行处理。 下面再回顾一下前面的简单的SWT程序的结构:

public static void main(String[] args) {Display display = new Display ();Shell shell = new Shell (display);......shell.open ();while (!shell.isDisposed ()) {if (!display.readAndDispatch ()) display.sleep ();}display.dispose ();}

while循环一段就是处理消息循环的开始,也就是说,一个SWT程序的主线程,就是对应的所谓的UI线程。

程序中什么地方是UI线程什么地方是非UI线程

  1. 主线程是UI线程
  2. 监听器方法中是UI线程 比如下面这段小程序:
Label label = new Label (shell, SWT.NONE);label.setText ("Enter your name:");Text text = new Text (shell, SWT.BORDER);text.setLayoutData (new RowData (100, SWT.DEFAULT));Button ok = new Button (shell, SWT.PUSH);ok.setText ("OK");ok.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {while(true) {System.out.println(1);try {Thread.sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}}}});

程序中模拟在点击按钮后,执行一段费时的操作,运行可以看到,程序处于无响应状态:

避免无响应

那么,如何避免程序进入无响应状态呢? 其实很简单,不要在UI线程中执行长时间的操作,如果必需要执行费时操作,就在另外的线程中执行:

ok.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {new Thread() {public void run() {while(true) {System.out.println(1);try {Thread.sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}}}}.start();}});

这样再次执行,可以看到点击按钮后,程序不再会进入无响应状态。

非UI线程访问UI

所以对控件的操作都必需在UI线程中进行,否则会抛出线程访问错误,还是以上面代码为例,我们现在改成打印text控件的文本:

ok.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {// 此处代码直接在监听器方法中,是UI线程new Thread() {public void run() {// 此处为另外一个单独线程,非UI线程while(true) {System.out.println(text.getText());try {Thread.sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}}}}.start();}});

运行程序,点击按钮,就会抛出下面的异常:

Exception in thread "Thread-0" org.eclipse.swt.SWTException: Invalid thread accessat org.eclipse.swt.SWT.error(SWT.java:4441)at org.eclipse.swt.SWT.error(SWT.java:4356)at org.eclipse.swt.SWT.error(SWT.java:4327)at org.eclipse.swt.widgets.Widget.error(Widget.java:476)at org.eclipse.swt.widgets.Widget.checkWidget(Widget.java:367)at org.eclipse.swt.widgets.Text.getText(Text.java:1350)at test.Snippet108$1$1.run(Snippet108.java:24)

对于这种在非UI线程访问UI的情况,需要用Display类的syncExec(Runnable)或asyncExec(Runnable)两个方法来执行:

ok.addSelectionListener(new SelectionAdapter() {@Overridepublic void widgetSelected(SelectionEvent e) {// 此处代码直接在监听器方法中,是UI线程new Thread() {public void run() {// 此处为另外一个单独线程,非UI线程 while(true) {// 非UI线程访问UIdisplay.syncExec(new Runnable() {@Overridepublic void run() {// 这段代码实际上会被放在UI线程中执行System.out.println(text.getText());}});try {Thread.sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}}}}.start();}});

注意上面的注释说明,syncExec(runnable)方法的参数runnable对象实际上是会被放在UI线程中执行的,所以要注意,不要把Tread.sleep()放到这个runnable里,否则同样会导致界面无响应。

syncExec和asyncExec方法的区别就是这两个方法一个会等待runnable执行完才返回,asyncExec方法则是立即返回,UI线程会在有空闲的时候去执行runnable。

那么,是否能够用asyncExec方法执行,同时把上面的sleep放到runnable中呢? 答案依然是不能,原因前面已经提到了,因为runnable实际上是会放到UI线程中执行的,如果这个runnable是非常耗时的,同样会让界面不断陷入每次1秒的无响应状态中, 也相当于新开一个线程执行耗时操作的目的就没有达到了。

读者可以试着根据上面的例子,自己写一个时钟程序,每秒钟刷新显示当前时间,注意不要让程序陷入无响应状态。 可以参考示例代码。

转载于:https://my.oschina.net/dollyn/blog/360620

SWT的UI线程和非UI线程相关推荐

  1. android 组件 线程,Android UI线程和非UI线程

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

  2. Android开发之UI线程和非UI线程

    这里又是老生畅谈的话了,前边已经有多篇文章针对线程进行探究解释,Android开发过程中线程的体现更是淋漓尽致.Android开发过程中涉及到的线程从大类上分可以归为两类:UI线程和非UI线程.本篇就 ...

  3. 守护线程与非守护线程的区别

    守护线程与非守护线程 最近在看多线程的Timer章节,发现运用到了守护线程,感觉Java的基础知识还是需要补充. Java分为两种线程:用户线程和守护线程 所谓守护线程是指在程序运行的时候在后台提供一 ...

  4. Java中的守护线程和非守护线程(转载)

    <什么是守护线程,什么是非守护线程> Java有两种Thread:"守护线程Daemon"(守护线程)与"用户线程User"(非守护线程). 用户线 ...

  5. 守护线程和非守护线程

    直觉上来讲,守护线程和main相关 Java中有两种线程,一种是用户线程,另一种是守护线程. 用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止(另一条执行路径) 守护线程当进程不存在或主 ...

  6. 多线程基础-守护线程与非守护线程

    守护线程与非守护线程 1.线程分类: 2.程序线程: 3.主线程与非守护线程 4.主线程与守护线程 5.主线程.守护线程.非守护线程 6. java虚拟机是如何退出的? 1.线程分类: 守护线程 非守 ...

  7. java守护线程与非守护线程

    java守护线程与非守护线程 代码逻辑 当前网上结论 1.主线程结束,守护线程跟着结束 2.只要存在任何一个非守护线程,守护线程就全部工作 测试代码 第一段代码 第二段代码 结论 代码逻辑 代码里面包 ...

  8. 守护线程是什么?守护线程和非守护线程的区别是?守护线程的作用是?

    守护线程是区别于用户线程,用户线程即我们手动创建的线程,而守护线程是程序运行的时候在后台提供一种通用服务的线程.垃圾回收线程就是典型的守护线程. 守护线程和非守护线程的区别是 public stati ...

  9. Android UI线程和非UI线程

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

最新文章

  1. delphi 判断鼠标 左右_外设评测HyperX Pulsefire Haste游戏鼠标分享
  2. 织梦DedeCMS播放本地视频文件插件
  3. 数字怎么横 竖排_从这些数字更深入了解打包箱房
  4. 括号配对问题 -- ACM解决方法
  5. 2015Cocos游戏开发大赛作品——人鱼塞壬
  6. PHP+MySQL 手工注入语句大全 推荐
  7. (王道408考研操作系统)第四章文件管理-第二节4:磁盘的管理
  8. 如何用 IDEA 提升十倍开发效率?
  9. java实现米和厘米比较好_java如何根据实际经、纬度和已知经、纬度做对比,计算出具体偏差米数。(以米为单位)...
  10. XXX 管理平台系统——项目风险
  11. 三伏天里小试牛刀andriod 开发 #华为云·寻找黑马程序员#
  12. python编码思维导图_Python入门之ATM+购物车代码版思维导图
  13. 如何在 Serverless K8s 集群中低成本运行 Spark 数据计算?
  14. 【论文写作】网上选课系统中模块设计如何写
  15. Centos7重置Mysql 8.0.1 root 密码
  16. C/C++程序员应聘常见面试题深入剖析(1)
  17. nslookup测试网络命令
  18. ps vita 说明书
  19. Flash鼠标拖尾效果——粒子
  20. c语言 proteus 延迟2秒_几种延时的汇编执行代码对比与总结

热门文章

  1. 研华数据采集卡如何采集压力信号转化为数字信号_涨知识啦!PLC编程中如何使用开关、模拟、脉冲量...
  2. 综合应用能力计算机类考什么用,综合应用能力考什么内容
  3. python 图片地址_python解码data:image开头的图片地址
  4. linux 服务器 重新启动 慢,Linux系统启动缓慢解决方法[阮胜昌]
  5. 2021高考一诊成绩查询,双流棠湖中学高2021届成都市“一诊”成绩已揭晓
  6. html超链接打开共享文件夹,教你如何访问共享文件夹
  7. 飞桨模型保存_史上最全解读|飞桨模型库重大升级,主流算法模型全覆盖
  8. flask双向映射语法
  9. 一段js动态操作table代码
  10. C#期末考试题,图书系统