8

你如何让你的应用程序多线程?你使用异步函数吗?还是你产生一个新线程?我认为异步函数已经产生了一个线程,所以如果你的工作只是做一些文件读取,那么懒惰并且只是在线程上产生你的工作只会“浪费”资源......那么使用线程时是否有某种设计或异步功能?

4

5 回答 5

7

如果您在谈论 .Net,请不要忘记ThreadPool。线程池也是异步函数经常使用的。产生大量线程实际上会损害您的性能。线程池旨在生成足够多的线程以最快地完成工作。因此,请使用线程池而不是创建自己的线程,除非线程池不能满足您的需求。

PS:留意微软的Parallel Extensions

于 2008-09-14T14:02:59.153 回答
6

如果你开始产生大量线程,产生线程只会浪费资源,一两个额外线程不会影响平台性能,事实上系统目前有超过 70 个线程供我使用,而 msn 正在使用 32 个(我真的有不知道信使如何使用这么多线程,特别是当它最小化并且没有真正做任何事情时......)

通常,产生线程的好时机是某些事情需要很长时间,但您需要继续做其他事情。

例如说计算将需要 30 秒。最好的办法是为计算生成一个新线程,以便您可以继续更新屏幕,并处理任何用户输入,因为如果您的应用程序在完成计算之前冻结,用户会讨厌它。

另一方面,创建线程来做几乎可以立即完成的事情几乎没有意义,因为创建(甚至只是使用线程池将工作传递给现有线程)的开销将高于仅在第一名。

有时您可以将您的应用程序分成几个单独的部分,这些部分在各自的线程中运行。例如,在游戏中,更新/物理等可能是一个线程,而图形是另一个线程,声音/音乐是第三个线程,网络是另一个线程。这里的问题是你真的必须考虑这些部分将如何交互,否则你可能会有更糟糕的表现,看似“随机”发生的错误,甚至可能会死锁。

于 2008-09-14T14:06:39.223 回答
2

我将支持Fire Lancer 的回答 - 创建自己的线程是处理大型任务或处理其他同步应用程序“阻塞”的任务的绝佳方式,您必须清楚地了解问题您必须以明确定义线程任务并限制其作用范围的方式来解决和开发。

举一个我最近研究的例子——一个 Java 控制台应用程序定期运行以通过基本上屏幕抓取 url、使用 DOM 解析文档、提取数据并将其存储在数据库中来捕获数据。

正如您所料,作为一个单线程应用程序,它花费了一段时间,对于 50kb 的页面,平均每秒大约 1 个 url。还不错,但是当您扩展到需要批量处理数千个网址时,那就不好了。

分析应用程序显示大部分时间活动线程处于空闲状态 - 它正在等待 I/O 操作 - 打开到远程 URL 的套接字、打开到数据库的连接等。这种情况很容易发生通过多线程改进。重写为多线程并且仅使用 5 个线程而不是 1 个线程,即使在单核 cpu 上,吞吐量也增加了 20 倍以上。

在这个例子中,每个“工作”线程都被明确地限制在它所做的事情上——打开远程一个远程 url,解析数据,将它存储在数据库中。所有“高级”处理——生成要解析的 url 列表、确定下一个、处理错误,都由主线程控制。

于 2008-09-14T14:55:09.123 回答
0

线程的使用使您可以更多地考虑应用程序需要线程的方式,并且从长远来看可以更容易地改进/控制您的性能。
异步方法使用起来更快,但它们有点神奇——很多事情都使它们成为可能——所以很可能在某些时候你需要一些它们不能给你的东西。然后您可以尝试滚动一些自定义线程代码。
这一切都取决于您的需求。

于 2008-09-14T14:05:05.793 回答
0

答案是“视情况而定”。

这取决于您要达到的目标。我将假设您的目标是提高性能。

最简单的解决方案是找到另一种提高性能的方法。运行分析器。寻找热点。减少不必要的IO。

下一个解决方案是将您的程序分成多个进程,每个进程都可以在自己的地址空间中运行。这是最简单的,因为各个进程不可能相互混淆。

下一个解决方案是使用线程。在这一点上,您正在打开一个主要的蠕虫罐头,所以从小处着手,并且只对代码的关键路径进行多线程处理。

下一个解决方案是使用异步 IO。通常只推荐给编写一些负载很重的服务器的人,即使那样我也宁愿重新使用现有的框架之一,抽象出细节,例如 C++ 框架 ICE,或 java 下的 EJB 服务器。

请注意,这些解决方案中的每一个都有多个子解决方案 - 有不同种类的线程和不同种类的异步 IO,每个都有略微不同的性能特征,但同样,最好让框架为您处理它。

于 2008-09-16T12:04:22.993 回答