在应用程序中有很多线程会适得其反吗?
Posted
技术标签:
【中文标题】在应用程序中有很多线程会适得其反吗?【英文标题】:Is having a lot of threads in an application counter productive? 【发布时间】:2015-12-02 10:49:11 【问题描述】:我目前正在尝试实现一个供个人使用的多线程数据库连接接口。这是使用 3 个类实现的
DatabaseManager
数据库连接实例为每个连接实例化一个新线程
Database
继承自 QThread 的对象,旨在在主线程中运行并公开接口以在工作对象上执行操作
DatabaseWorker
在管理单个数据库连接的工作线程中运行事件循环的工作对象,等待查询并通过 Qt:QueuedConnections(信号/插槽)传递结果
当不再使用连接时(显式调用close()
方法),它的相关事件循环将停止并删除线程。这样做的目的是尽量减少线程的创建和删除。
到目前为止,这种架构在线程数量有限(通常少于 10 个连接)的情况下取得了很大的成功。我的主要问题是,如果我有 100 多个连接,这意味着一个应用程序有 100 多个线程,我不知道它会如何表现,这会带来我的主要问题
在应用程序中使用大量线程会适得其反吗?如果我同时打开 50/100/500/1000 个连接会发生什么?如果我这样做,I/O 数据库操作将需要很长时间才能完成(它最初并不是为此而设计的),但是有多少延迟是由线程数引起的?
【问题讨论】:
这取决于运行应用程序的硬件。如果您实际上可以在不同的内核上运行线程,那么只要调度程序不会阻塞每个单独的内核,您就会有所收获。这是线程作业真正独立的通常警告。这里没有明确的答案,只有剖析才能知道。 不知道 - 问问你的数据库:) 100,甚至 1000,线程本身并不是一个特殊的问题。您的数据库的特征可能是.. 硬件是 Intel I5 2.4GHz,有 6 个硬件线程,打开很多数据库连接不是问题,因为我可以在不同的服务器上打开 100 个连接到 100 个不同的数据库。我现在只关心我的本地应用程序 是的...问题是,这取决于您的 rDB 接口。如果每个 DB 调用都被互斥锁完全锁定,那么无论您是 1 核还是 64 核都没有关系:( 使用每个连接线程的方法,一旦达到大约 800 个连接,如果您必须为大量连接中的每一个都做一点工作,您就会开始看到严重的性能问题。跨度> 【参考方案1】:线程数本身并不是一个大问题。每个都使用一些内存,但对于现代机器来说,开销并不大。
主要问题出现在所有这些线程开始尝试同时工作时,它们开始争夺资源,并且您最终得到的结果可能比从少数线程更智能地工作中获得的结果要慢。
线程池是这种情况的常见解决方案,其中任务排队等待执行,并且您有一个线程池,其中包含适合您机器的线程数(例如每个核心一个线程)来处理项目离开队列。如果您的线程花费大量时间空闲等待响应,则可能需要更多线程,但如果它们不断进行计算,那么添加更多线程实际上可能会减慢速度。
衡量性能并进行相应调整:)“直觉”在处理性能时非常不可靠。
【讨论】:
我同意。有些人讨厌线程,但是如果您使用线程池,您可以避免过多的线程,同时仍然获得类似于“每个连接一个线程”模型的应用程序逻辑。在编写套接字代码时,我真的很讨厌必须在套接字上返回半读数据并做很多丑陋的簿记。线程,或者在某些情况下,协程允许更简洁的代码,这也意味着更少的错误。不过,调试线程应用程序可能会很痛苦......【参考方案2】:我会说是的,这会适得其反。每个线程都为其堆栈空间占用了大量内存,如果您只有 6 个内核,则无论如何都无法并行运行 100 多个线程。改用线程池,例如通过 KF5 ThreadWeaver 或 Qt Concurrent 并注意理想的线程数。
【讨论】:
理想的线程数与 CPU 密集型操作相关。数据库访问正在阻塞 IO 操作。如果我正好有 6 个线程,我的应用程序将有 80% 的时间处于休眠状态,等待来自服务器的响应。我肯定需要更多 ThreadWeaver 和 Qt Concurrent 都允许您调整池中的线程数。使用分析为您的用例找到最佳值,理想的线程数是安全的第一选择,当然比让它不受约束并旋转数百个潜在的临时线程要好。以上是关于在应用程序中有很多线程会适得其反吗?的主要内容,如果未能解决你的问题,请参考以下文章
正确关闭线程池:shutdown 和 shutdownNow 的区别
Tomcat服务器关闭时,如果在线程中使用JDBC数据库连接,它们会被释放吗?