`
zhouchaofei2010
  • 浏览: 1104283 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

(转)GUI为什么不设计为多线程

 
阅读更多

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

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

单线程消息队列机制

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

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

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

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

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

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

l AndroidAcitvity.runOnUiTheadHandler.postAsyncTask

l SwingSwingUtilities.invokeLater

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

GUI为什么不设计为多线程

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

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

https://weblogs.java.net/blog/kgh/archive/2004/10/multithreaded_t.html

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

多线程GUI加锁困难

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

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

 

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

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

分享到:
评论

相关推荐

    GUI中用线程实现倒计时

    ### GUI中用线程实现倒计时的知识点详解 #### 一、背景介绍 ...通过对Swing组件的应用、多线程的处理以及事件监听器的设计,不仅能够有效提升GUI程序的用户体验,还能加深开发者对于Java多线程机制的理解。

    交通灯设计(GUI)多线程

    在设计多线程部分,我们需要考虑如何协调各个线程的执行顺序。一种常见方法是使用wait()和notifyAll()方法,这需要将所有线程置于同一个对象的监视器上。当一个线程完成其任务(如红灯变绿)时,它会唤醒其他等待的...

    Java用多线程GUI实现购买车票界面

    Java是一种广泛使用的编程语言,尤其在开发图形用户界面(GUI)和处理多线程应用程序时。在这个场景中,我们讨论的是如何使用Java来构建一个模拟车票购买的GUI,并利用多线程技术来提高程序的响应性和用户体验。下面...

    用java写的多线程聊天程序GUI界面socket实现

    总的来说,这个项目提供了一个很好的实践平台,帮助开发者深入理解Java的网络编程、多线程和GUI设计。通过研究和修改这个项目,你可以进一步提升自己的Java编程技能,尤其是对于网络应用的开发能力。

    基于Java多线程和GUI的贪吃蛇

    在本项目"基于Java多线程和GUI的贪吃蛇"中,开发者利用了Java的强大功能,构建了一个具有用户友好的图形用户界面(GUI)的游戏,并融入了多线程技术来实现游戏的流畅运行。以下是关于这个项目所涉及的知识点的详细...

    【源代码】Pythone+PyQt5+爬虫+多线程 : 豆瓣陶书工具(GUI)

    标题中的"【源代码】Pythone+PyQt5+爬虫+多线程 : 豆瓣陶书工具(GUI)"表明这是一个使用Python编程语言,结合PyQt5图形用户界面库,实现的一个爬虫程序,该程序具备多线程功能,并且主要目标是通过抓取豆瓣网站的数据...

    多线程GUI界面交互示例

    在开发桌面应用程序时,尤其是图形用户界面(GUI)应用,多线程技术是必不可少的,因为它可以提升用户体验,保持界面的响应性。本示例主要关注如何在GUI中实现多线程交互,以及如何利用`backgroundWorker`组件来避免...

    两层电梯模型Java多线程配合多媒体模拟GUI程序

    总的来说,这个两层电梯模型Java多线程配合多媒体模拟GUI程序是一个综合性的实践项目,涵盖了Java多线程、GUI编程、多媒体处理、状态机设计、数据结构与算法等多个关键知识点,是提升Core Java技能的绝佳实践。...

    WHUT-java多线程实验-第四周-GUI.zip

    Java多线程与GUI是Java编程中的重要领域,尤其在开发复杂的桌面应用程序时,它们的结合使得程序能够同时处理用户交互和后台计算。本实验基于WHUT(武汉理工大学)面向对象多线程的教学内容,专注于Java图形用户界面...

    基于Python+PyQt制作GUI的劲爆多进程和多线程下载器

    【作品名称】:基于Python+PyQt制作GUI的劲爆多进程和多线程下载器 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【项目介绍】: ...

    java多线程聊天程序GUI界面socket实现.rar

    Java多线程聊天程序是基于GUI(图形用户界面)和Socket通信实现的,它允许多个用户通过网络进行实时交流。...这个程序不仅有助于理解Java的并发编程,同时也对网络编程和GUI设计有很好的实践意义。

    C++ QT实现多线程【嵌入式QT GUI设计】.zip

    这个项目"嵌入式C++ QT GUI设计"显然关注的是如何在嵌入式系统中利用Qt进行高效的多线程编程,以实现更加流畅、响应迅速的GUI应用。以下是对这个主题的详细阐述: 首先,Qt库提供了丰富的类和函数,使得开发人员...

    RV1126实现GUI多线程【QT GUI可视化】.zip

    1. **资源管理**:嵌入式系统的内存和CPU资源有限,因此在设计多线程应用时要合理分配资源,避免过度消耗导致系统性能下降。 2. **线程同步**:为了确保数据的一致性和完整性,多线程间的通信需要进行同步,QT提供...

    基于Java的GUI多线程下载器的设计与实现.pdf

    综上所述,Java的GUI多线程下载器的设计与实现涉及了多个关键领域的知识和技能,包括但不限于GUI编程、多线程编程、网络编程、文件操作、异常处理等。通过采用合理的架构设计模式和编程技术,可以构建出功能强大、...

    Java毕业设计-多线程与线程安全实践-基于Http协议的断点续传.zip

    总体来说,这个Java毕业设计项目旨在通过实现多线程和断点续传功能,让学生深入理解和掌握Java多线程编程、线程安全控制、HTTP协议的应用以及文件处理等关键技术,为日后的软件开发工作打下坚实的基础。

    基于Java的GUI多线程下载器的设计与实现.zip

    在本项目中,“基于Java的GUI多线程下载器的设计与实现”是一个旨在演示如何使用Java编程语言构建一个图形用户界面(GUI)程序,该程序能够利用多线程技术进行文件下载。这样的下载器可以提高文件下载速度,因为它将...

    基于VB实时数据采集与处理的多线程设计

    通过合理设计多线程结构,可以显著提升软件的性能和用户体验,解决实时数据采集引发的程序响应问题,对于提高测控系统、数据分析系统等领域的软件开发水平具有重要意义。 总之,《基于VB实时数据采集与处理的多线程...

Global site tag (gtag.js) - Google Analytics