• 6155阅读
  • 0回复

[转载]Qt经典—我应该什么时候使用线程 [复制链接]

上一主题 下一主题
离线zjhcool
 
只看楼主 倒序阅读 楼主  发表于: 2011-03-15
当你不得不使用一个阻塞式API时

当你需要(通过信号和槽,或者是事件、回调函数)使用一个没有提供非阻塞式API的库或者代码时,为了阻止冻结事件循环的唯一可行的解决方案是开启一个进程或者线程。由于创建一个新的进程的开销显然要比开启一个线程的开销大,后者往往是最常见的一种选择。
  
  

这种API的一个很好的例子是地址解析 方法(只是想说我们并不准备谈论蹩脚的第三方API, 地址解析方法它是每个C库都要包含的),它负责将主机名转化为地址。这个过程涉及到启动一个查询(通常是远程的)系统:域名系统或者叫DNS。尽管通常情况下响应会在瞬间发生,但远程服务器可能会失败:一些数据包可能会丢失,网络连接可能断开等等。简而言之,我们也许要等待几十秒才能得到查询的响应。
UNIX系统可见的标准API只有阻塞式的(不仅过时的gethostbyname(3)是阻塞式的,而且更新的 getservbyname(3) 以及getaddrinfo(3)也是阻塞式的)。QHostInfo [doc.qt.nokia.com], 它是一个负责处理域名查找的Qt类,该类使用了QThreadPool 从而使得查询可以在后台进行)(参见here [qt.gitorious.com]);如果屏蔽了多线程支持,它将切换回到阻塞式API).
另一个简单的例子是图像装载和放大。QImageReader [doc.qt.nokia.com] 和QImage [doc.qt.nokia.com]仅仅提供了阻塞式方法来从一个设备读取图像,或者放大图像到一个不同的分辨率。如果你正在处理一个非常大的图像,这些处理会持续数(十)秒。
当你想扩展至多核
多线程允许你的程序利用多核系统的优势。因为每个线程都是被操作系统独立调度的,因此如果你的应用运行在这样多核机器上,调度器很可能同时在不同的处理器上运行每个线程。
例如,考虑到一个通过图像集生成缩略图的应用。一个_n_ threads的线程农场(也就是说,一个有着固定数量线程的线程池),在系统中可见的CPU运行一个线程(可参见 QThread::idealThreadCount()),可以将缩小图像至缩略图的工作交付给所有的进程,从而有效地提高了并行加速比,它与处理器的数量成线性关系。(简单的讲,我们认为CPU正成为一个瓶颈)。
什么时候你可能不想别人阻塞
这是一个很高级的话题,你可以忽略该小节。一个比较好的例子来自于Webkit里使用的QNetworkAccessManager 。Webkit是一个时髦的浏览器引擎,也就是说,它是一组用于处理网页的布局和显示的类集合。使用Webkit的Qt widget是QWebView。
QNetworkAccessManager 是一个用于处理HTTP任何请求和响应的Qt类,我们可以把它当作一个web浏览器的网络引擎;所有的网络访问被同一个QNetworkAccessManager 以及它的QNetworkReplys 驻足的线程所处理。
尽管在网络处理时不使用线程是一个很好的主意,它也有一个很大的缺点:如果你没有从socket中尽快地读取数据,内核的缓存将会被填满,数据包可能开始丢失而且传输速率也将迅速下降。
Sokcet活动(即,从一个socket读取一些数据的可见性)由Qt的事件循环管理。阻塞事件循环因此会导致传输性能的损失,因为没有人会被通知将有数据可以读取(从而没人会去读数据)。
但究竟什么会阻塞事件循环呢?令人沮丧地回答: WebKit它自己!只要有数据被接收到,WebKit便用其来布局网页。不幸地是,布局处理过程相当复杂,而且开销巨大。因此,它阻塞事件循环的一小段时间足以影响到正在进行地传输(宽带连接这里起到了作用,在短短几秒内就可填满内核缓存)。
总结一下上述所发生的事情:
WebKit提出了一个请求;
一些响应数据开始到达;
WebKit开始使用接收到的数据布局网页,从而阻塞了事件循环;
数据被OS接受,但没有一个正在运行的事件循环为之派发,所以并没有被QNetworkAccessManager sockets所读取;
内核缓存将被填满,传输将变慢。
网页的总体装载时间因其自发引起的传输速率降低而变得越来越坏。
诺基亚的工程师正在试验一个支持多线程的QNetworkAccessManager来解决这个问题。请注意因为 QNetworkAccessManagers 和QNetworkReplys 是QObjects,他们不是线程安全的,因此你不能简单地将他们移到另一个线程中并且继续在你的线程中使用他们,原因在于,由于事件将被随后线程的事件循环所派发,他们可能同时被两个线程访问:你自己的线程以及已经它们驻足的线程。
本文由Venus分享  


我的博客地址: http://newfaction.net
快速回复
限100 字节
 
上一个 下一个