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

在我们这批新人转正评审的时候,我师父问了我的小伙伴一个问题:为什么一些更新界面的方法只能在主线程中调用?师父没有问我这个问题,让知其然但不知其所以然的我有种侥幸逃过一难的心情。我想如果回答那是因为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走的是个自顶向下的流程:

bc80c26803244feefe644d3e7700e257.png

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

4cc6555f0a80cf72c823cd78dfab71da.png

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/523450.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

行啊,人工智能玩大了!

戳蓝字“CSDN云计算”关注我们哦!是的 ,你没猜错!就是人工智能!AI的炽手可热程度和重要性无需多提。最近,笔者在网上发现了一个报告,报告名字:《BAT人工智能领域人才发展报告》,发现…

java xml注入bean_Spring实战之通过XML装配bean

尽管Spring长期以来确实与XML有着关联,但现在需要明确的是,XML不再是配置Spring的唯一可选方案。Spring现在有了强大的自动化配置和基于Java的配置,XML不应该再是你的第一选择了。不过,鉴于已经存在那么多基于XML的Spring配置&…

Docker 存储选型,这些年我们遇到的坑

戳蓝字“CSDN云计算”关注我们哦!技术头条:干货、简洁、多维全面。更多云计算精华知识尽在眼前,get要点、solve难题,统统不在话下!随着Docker 容器技术的不断发展和业内对Docker 的使用不断深入,大家已经不…

mysql主从复制之异常解决--- Slave_IO_Running: NO

关于 Slave_IO_Running: NO 的错误其实有很多原因, 文章目录1. 解决问题的思路2. 异常信息3. 问题定位:由于uuid相同,而导致触发此异常4. 解决方案5. 服务器背景6. 具体解决方案7. 重新启动mysql8. 登录mysql,重启slave&#xff0…

企业实战_11_MyCat垂直拆分相关配置

接上一篇:企业实战_10_MyCat Mysql 主复制总结 https://gblfy.blog.csdn.net/article/details/118652742 文章目录一、准备工作1. 实现思路2. 配置MyCat垂直分库3. 环境配置4. 在master节点创建mycat用户5. 赋予操作数据库权限二、schema.xml文件配置2.1. 基础模板 …

K8S精华问答 | 如何监控部署在Docker容器上的应用程序?

kubernetes,简称K8S,是用8代替8个字符“ubernete”而成的缩写。是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单并且高效(powerful),Kubernetes提供了应…

带你全面了解Http和Https

戳蓝字“CSDN云计算”关注我们哦!作者: 左大人 | 来源 公众号 程序员小乐来源:jianshu.com/p/27862635c07700 前言 Http和Https属于计算机网络范畴,但作为开发人员,不管是后台开发或是前台开发,都很有必要掌握它们。在…

企业实战_05_MyCat用户密码加密

接上一篇:企业实战_04_MyCat常用配置文件详解 https://gblfy.blog.csdn.net/article/details/100112080 文章目录1. 加密简述2. 加密目录3. 执行加密4. 添加加密属性5. 添加密文6. 测试是否可用声明:需要提前安装mysql Linux centos7 安装 MySQL5.7.x 1. 加密简述 …

大数据从哪里来?| 技术头条

戳蓝字“CSDN云计算”关注我们哦!作者:Feng来源:哈尔的数据城堡现代商业市场是一个数据驱动的环境,可以说不论技术怎么更新换代,数据都有着不可替代的地位,而且抛开数据谈大数据服务就是瞎扯,没…

java算法判断链表有没有闭环_前端算法系列之二:数据结构链表、双向链表、闭环链表、有序链表...

前言上一次我们讲到了数据结构:栈和队列,并对他们的运用做了一些介绍和案例实践;我们也讲到了怎么简单的实现一个四则运算、怎么去判断标签是否闭合完全等等,anyway,今天接着和大家介绍一些数据结构:链表链…

苹果宣布加入CNCF;华为要求美国运营商支付专利费;微软删除最大的公开人脸识别数据集...

戳蓝字“CSDN云计算”关注我们哦!嗨,大家好,重磅君带来的【云重磅】特别栏目,如期而至,每周五第一时间为大家带来重磅新闻。把握技术风向标,了解行业应用与实践,就交给我重磅君吧!重…

企业实战_14_MyCat跨分片查询_全局表

接上一篇:企业实战_13_MyCat清除冗余数据 https://gblfy.blog.csdn.net/article/details/100057317 文章目录一、跨分片查询验证1. 登录mycat2. 使用逻辑数据库1.3. 执行跨分片查询1.4. 异常信息,问题定位1.5. 表分布1.6. 跨分片查询的解决方式1.7. 场景…

java创建四叉树_Java实现 LeetCode 427 建立四叉树

427. 建立四叉树我们想要使用一棵四叉树来储存一个 N x N 的布尔值网络。网络中每一格的值只会是真或假。树的根结点代表整个网络。对于每个结点, 它将被分等成四个孩子结点直到这个区域内的值都是相同的.每个结点还有另外两个布尔变量: isLeaf 和 val。isLeaf 当这个节点是一个…

漫画:什么是二分查找?

戳蓝字“CSDN云计算”关注我们哦!作者 | 蠢萌的小灰来源 | 程序员小灰————— 第二天 —————什么意思呢?我们来举两个栗子:给定一个有序数组 2,5,7,9,12,14,20&…

mysql和mysqldump出现command not found 问题解决

mysql和mysqldump出现command not found 问题解决 一、给mysql配置环境变量 #找到mysql安装路径 cd /app/mysql-5.7.25 #vim /etc/profile export MYSQL_HOME/app/mysql-5.7.25 :${MYSQL_HOME}/bin二、建立软连接 1、查找mysql安装路径 find / -name mysql 通常mysql安装路径…

如何给老婆解释什么是微服务?(文末有福利)

戳蓝字“CSDN云计算”关注我们哦!程序员有了老婆之后就是累,上次好不容易给她解释了什么是Restful,这不,麻烦又来了…一个周日的清晨,阳光洒在我的脸上,慢慢把我唤醒。我翻过身,感觉好像少了些什…

oracle19c连接MySQL_oracle19c的安装和使用navicat连接oracle数据库

一,数据的安装Oracle官方下载链接:https://www.oracle.com/downloads/#category-database首先去oracle官网下载,数据库里面包含了客户端,所以不需要再下载客户端了注意:有的人不下载数据库,只下载客户端为了…

Mycat_MySql更新数据库失败 --read-only

接上一篇:企业实战_20_Mycat-Web之UI监控 https://blog.csdn.net/weixin_40816738/article/details/100100053 #登录数据库 mysql -uroot -p #使用指定数据库 use 数据库名 #查看数据库处于什么状态下 show variables like read-only; #关闭read-only属性状态 set g…

Linux 运维必备的 13 款实用工具,拿好了

戳蓝字“CSDN云计算”关注我们哦!来源 | 高效运维本文介绍几款 Linux 运维比较实用的工具,希望对 Linux 运维人员有所帮助。1. 查看进程占用带宽情况 - NethogsNethogs 是一个终端下的网络流量监控工具可以直观的显示每个进程占用的带宽。下载&#xff1…

企业实战_12_MyCat水平扩展_分库分表

接上一篇:企业实战_11_MyCat垂直拆分相关配置 https://gblfy.blog.csdn.net/article/details/100055838 文章目录一、概念理论理解1. 垂直拆分理解2. 水平扩展理解3. 水平扩展案例4. 水平扩展场景5. 水平拆分原则6. 水平扩展架构图二、关键问题解决方案2.1. 分片后如…