在我们这批新人转正评审的时候,我师父问了我的小伙伴一个问题:为什么一些更新界面的方法只能在主线程中调用?师父没有问我这个问题,让知其然但不知其所以然的我有种侥幸逃过一难的心情。我想如果回答那是因为Android GUI库是单线程消息机制的,更新界面的操作必须放到主线程中执行,那师父可能继续问为什么Android GUI要设计成单线程的,我就不知道了。

为什么它非得设计为单线程的?多线程不是更好吗?带着点好奇感和求知欲以及鄙视权威的无畏精神我在google中展开了搜索,并最终找到了一个令我满意的解释,欣喜之余将我的理解分析给大家。

单线程消息队列机制

首先我还是说一下我对GUI单线程消息队列机制的理解,这是我大学里几年编程经验赚来的知其然的部分。

Android、Swing、MFC等的GUI库都使用单线程消息队列机制来处理绘制界面、事件响应等消息,在这种设计中,每个待处理的任务都被封装成一个消息添加到消息队列中。消息队列是线程安全的(消息队列自己通过加锁等机制保证消息不会在多线程竞争中丢失),任何线程都可以添加消息到这个队列中,但是只有主线程(UI线程)从中取出消息,并执行消息的响应函数,这就保证了只有主线程才去执行这些操作。

单线程消息队列机制存在一个问题:消息响应函数中不能有耗时长的、计算密集型的操作,因为主线程在努力地处理这样的操作的时候就无法去处理其它的积压在消息队列中的绘制消息、事件消息了(一个消息处理完了主线程才会去队列中取下一个消息),这时候就会出现按键无响应、点击无反应的情况。

但这个问题有完美的解决方案,我们可以在消息响应函数中启动另一个工作线程(Worker Thread)来执行耗时操作,这样在线程启动起来后这个消息就算处理完了,主线程可以取下一个消息了,这时候主线程和还未执行完计算任务的工作线程就在操作系统的调度下并驾齐驱地狂奔了(调度算法会保证两个线程并发或并行地执行,不会专宠某个线程)。

一般我们在耗时任务执行完后还要更新界面展示计算的结果,由于我们不能直接在工作线程中更新界面,所以可能有些小伙伴直接在消息响应函数中线程start后就接着调用join来等待线程结束以更新界面,这其实相当于把耗时任务直接放在主线程去执行,因为在消息响应函数中join其实就是主线程在join,积压的消息是得不到处理的。正确的处理办法是将耗时任务改为异步通知机制,即工作线程向消息队列中添加消息以通知主线程耗时任务完成了,这样主线程在启动工作线程后就不需要主动地去调查任务的进展了,“任务结束的时候它会通知我的”,主线程如是说。

工作线程向主线程的消息队列添加消息的常用方法如下:

l Android:Acitvity.runOnUiThead、Handler.post、AsyncTask

l Swing:SwingUtilities.invokeLater

l Win32、MFC:自定义用户消息,在工作线程中PostMessage

GUI为什么不设计为多线程

大部分的GUI toolkits都是设计为上面的单线程消息队列机制,为什么不设计为多线程的呢?如果GUI是多线程的,CPU又是多核的话,多个CPU核心可以并行地执行绘制等操作,界面响应的速度应该是成倍提升的;而且就算是其中有多线程共享的资源加锁不就行了吗?

在google搜索的过程中我看到了负责Swing开发的一个大师的一篇博客《Multithreaded toolkits: A failed dream?》:

从中我了解到开发多线程的GUI toolkits是一件吃力不讨好的事,不仅开发难度大Bug多多,用起来也未必可以获得理想中的效果,其中的死锁和竞争,大师们也感到头疼。

多线程GUI加锁困难

为什么这么困难?大师讲了一个例子,我们通过用户级的代码去改变界面如TextView.setText走的是个自顶向下的流程:

而系统底层发起的如键盘事件、点击事件走的是个自底向上的流程:

这样就麻烦了,因为为了避免死锁,每个流程都要走一样的加锁顺序,而GUI中的这两个流程却是完全相反的,如果每一层都有一个锁的话加锁就是个难以完成的任务了,而如果每一层都共用一个锁的话,那就跟单线程没区别了。

于是GUI toolkits的开发者就“不负责任”地把GUI设计成了单线程消息队列机制,然后他们还说界面更新一般不是瓶颈,单线程足够了。然后我瞬间想到了3D游戏,单线程对于3D应该是很吃力的,但实际上负责3D绘制的是显卡的GPU,GPU不像CPU那样事无巨细、事必亲躬、鞠躬尽瘁、死而后已,只负责画好它的图就可以了,所以并行起来不是件困难的事。

http://blog.csdn.net/liuqiaoyu080512/article/details/12895005#t1

java加锁多线程改为单线程_GUI为什么不设计为多线程(用户事件和底层事件的流程是相反的,每层都加锁效率太低,共用一把锁那就是单线程)...相关推荐

  1. 执行效率太低又怎样? Python 照样火过 Java、C/ C++

    点击上方"CSDN",选择"置顶公众号" 关键时刻,第一时间送达! 世界上有成百上千种编程语言,时代更迭下不断有新的语言产生和消亡,但 Java 的江湖地位始终 ...

  2. GUI为什么不设计为多线程?

    GUI为什么不设计为多线程? 用户事件和底层事件的流程是相反的,每层都加锁效率太低,共用一把锁那就是单线程 为什么一些更新界面的方法只能在主线程中调用?那是因为Android GUI库是单线程消息机制 ...

  3. java如何确保单线程_java – 任何单线程程序如何成为有效的多线程程序?

    注意,该语句并不意味着任何正确的单线程程序也是正确的多线程程序,作者只是说明有可能将任何单线程程序转换为在多线程环境中执行. 但是,如果程序在单线程环境中已经不正确,那么在更复杂的多线程环境中它可能不 ...

  4. 「JAVA知识每日一问」:Redis6.0为什么引入多线程?

    前言 Redis 官方在 2020 年 5 月正式推出 6.0 版本,提供很多振奋人心的新特性,所以备受关注. 一键获取Redis合集资料文档 提供了啥特性呀?知道了我能加薪么? 主要特性如下: 多线 ...

  5. Java程序员从笨鸟到菜鸟之(十一)多线程讲解

    多线程是Java应用程序的一个特点,掌握java的多线程也是作为一java程序员必备的知识.多线程指的是在单个程序中可以同时运行多个同的线程执行不同的任务.线程是程序内的顺序控制流,只能使用分配给序的 ...

  6. 【JAVA知识每日一问】:Redis6.0为什么引入多线程?

    前言 Redis官方在 2020 年 5 月正式推出 6.0 版本,提供很多振奋人心的新特性,所以备受关注. 提供了啥特性呀?知道了我能加薪么? 主要特性如下: 多线程处理网络 IO: 客户端缓存: ...

  7. 为什么ui框架设计成单线程_评估UI设计的备忘单

    为什么ui框架设计成单线程 Whether you're evaluating your design proposals or giving feedback to a colleague duri ...

  8. java 8代码 改 java7_Java 8 到 Java 14,改变了哪些你写代码的方式?

    前几天,JDK 14 正式发布了,这次发布的新版本一共包含了16个新的特性. 其实,从Java8 到 Java14 ,真正的改变了程序员写代码的方式的特性并不多,我们这篇文章就来看一下都有哪些. La ...

  9. 020.day20 线程概述 多线程优缺点 线程的创建 线程常用方法 生命周期 多线程同步...

    目录 多线程 一.线程概述 四.线程常用方法 多线程 一.线程概述 1. 进程 正在执行的应用程序(java.exe),一个可执行的程序一次运行的过程 独立性:不同进程之间相互独立 动态性:是一直活动 ...

最新文章

  1. 浙大 CBIST团队发布高质量的多中心MRI公开数据集
  2. EditText的各种属性
  3. WebBrowser控件参数解释
  4. 《X86汇编语言:从实模式到保护模式》读书笔记之引言
  5. SpringCloud-Eureka-服务注册是如何发起的
  6. Firefly支持AI引擎Tengine,性能提升,轻松搭建AI计算框架
  7. 微信跳一跳高分系列三:用 adb 破解微信跳一跳小程序
  8. 为什么写公众号,为什么改名字
  9. 使用DPAPI加密或解密你的数据
  10. colorpix取色小工具_我发现一款神器!它集合了 60 多个超实用的工具
  11. 廖雪峰Java2面向对象编程-6Java核心类-5枚举类
  12. [Win32]创建模态窗口
  13. thinkphp5 图片压缩旋转_26套经典压缩机结构设计:有多少人知道内部结构是这样的...
  14. paip.php调试脱离IDE VC59
  15. 【设计模式】模板模式
  16. 研究生阶段记录3-PCR介绍
  17. 使用Texmacs帮助您写格式规范统一的BLOG
  18. 《财务共享服务》读书笔记
  19. 清翔电子51单片机小结——可调表时钟
  20. 解决QQ登录SDK不能网页授权登录的问题

热门文章

  1. Quick BI的可视分析之路
  2. 技术干货 | 源码解析 Github 上 14.1k Star 的 RocketMQ
  3. 如何在一周内上线50个用户增长策略
  4. 干货|Spring Cloud Stream 体系及原理介绍
  5. 重磅!阿里云发布业界首款SaaS化防火墙
  6. Nacos服务发现控制台预览
  7. 阿里:千亿交易背后的0故障发布
  8. Gartner:2020年全球IaaS公有云服务市场增长40.7%
  9. 打破云原生时代存储瓶颈,SmartX 发布 K8s 云原生存储 IOMesh
  10. 实锤!Python 真没你想的那么简单…