【问题标题】:Threads or asynch?线程还是异步?
【发布时间】:2010-09-08 20:20:52
【问题描述】:

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

【问题讨论】:

    标签: multithreading language-agnostic


    【解决方案1】:

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

    PS:请留意来自 Microsoft 的 Parallel Extensions

    【讨论】:

      【解决方案2】:

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

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

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

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

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

      【讨论】:

        【解决方案3】:

        我会第二个 Fire Lancer's 回答 - 创建自己的线程是处理大型任务或处理否则会“阻塞”到同步应用程序的其余部分的任务的绝佳方式,但是 你必须清楚地了解你必须解决的问题,并以明确定义线程任务并限制其作用范围的方式进行开发。

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

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

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

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

        【讨论】:

          【解决方案4】:

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

          【讨论】:

            【解决方案5】:

            答案是“视情况而定”。

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

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

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

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

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

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

            【讨论】:

              猜你喜欢
              • 2016-01-06
              • 1970-01-01
              • 2019-01-17
              • 2023-03-20
              • 2017-06-22
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多