什么时候适合多线程?

时间:2012-06-29 17:41:34

标签: java multithreading concurrency

我认为我“获得”Java的多线程基础知识。如果我没有弄错的话,你需要做一些大工作,弄清楚你将如何将其分成多个(并发)任务。然后,您将这些任务实施为RunnableCallable,并将它们全部提交给ExecutorService。 (所以,首先,如果我误解了这么多,请先纠正我!!!

其次,我必须想象你在run()call()中实现的代码必须尽可能“并行化”,使用非阻塞算法等。这就是困难的部分是(编写并行代码)。 正确?不正确?

但是我仍然使用Java并发的真正问题(我猜一般的并发性),以及这个问题的真正主题是:

  

什么时候首先适合多线程?

我在Stack Overflow上看到了另一个问题的例子,其中海报提议创建多个线程来读取和处理一个巨大的文本文件(书籍 Moby Dick ),一个回答者评论说多线程为了从磁盘读取是一个可怕的想法。他们的理由是因为你有多个线程引入了上下文切换的开销,在已经很慢的进程(磁盘访问)的顶层

所以这让我思考:什么类型的问题适合多线程,哪些类型的问题应该总是序列化?提前谢谢!

7 个答案:

答案 0 :(得分:8)

多线程有两个主要优点,IMO:

  • 能够在多个CPU /核心之间分配密集型工作:不是让4个CPU中的3个空闲并在单个CPU上执行所有操作,而是将问题分成4个部分,让每个CPU独立工作。这减少了执行CPU密集型任务所需的时间,并证明了您在多CPU硬件上花费的资金。
  • 减少许多任务的延迟。假设4个用户向Web服务器发出请求,请求全部由单个线程处理。假设第一个请求进行了非常长的数据库查询。线程处于空闲状态,等待查询完成,其他3个用户等待此请求完成以获取其小网页。如果您有4个线程,即使使用单个CPU,也可以在数据库服务器执行长数据库查询时处理第二,第三和第四个请求,并且所有用户都满意。因此,当您阻止IO调用时,多线程尤为重要,因为那些阻塞IO调用会让CPU空闲,而不是执行其他一些等待任务。

注意:从多个线程读取同一磁盘的问题是,不是按顺序读取整个长文件,而是强制磁盘在每个上下文切换时在磁盘的各个物理位置之间切换。由于所有线程都在等待磁盘读取完成(它们是IO绑定的),这使得读取速度比单个线程读取所有内容时慢。但是一旦数据在内存中,就可以在线程之间分割工作。

答案 1 :(得分:5)

  

这让我思考:哪类问题适合   多线程,应该始终序列化哪类问题?

基本上,CPU密集型任务(例如,执行大量数据处理,例如内存中排序)应该并行化(如果可能),并且I / O绑定任务应保持顺序(如磁盘I / O)。这是一般性建议,当然也有一些例外。

答案 2 :(得分:3)

  

这让我思考:什么类型的问题适合多线程,哪些类型的问题应该总是序列化?

当您使用Swing组件构建GUI时,有时您通过单击按钮(作为示例)要执行的任务需要很长时间,以至于您在执行任务时会锁定GUI。 / p>

因此,您在另一个线程中执行该任务,因此您可以保持GUI线程(Swing工作线程)响应Swing组件。

答案 3 :(得分:3)

多线程对以下内容很有价值:

  • 在多个CPU或多个核心之间分配工作。
  • 执行冗长任务时保持响应(例如,加载文件,执行计算)。
  • 执行可能阻止的操作(例如,从套接字读取)时保持响应。

答案 4 :(得分:1)

我更喜欢这种方式......

  1. 基于GUI的应用程序中,线程非常重要。

  2. 在Java中,GUI由Event Dispatcher Thread处理。 总是建议保持 UI工作在UI线程上,非UI工作在非UI线程上。 假设您按下按钮,然后向某个Web服务器发送http请求,在服务器上进行处理,然后它返回结果.. 如果您没有创建非UI线程来处理此作业,那么除非收到网络服务器的回复,否则您的GUI将不再响应。

  3. 同时完成多项工作的情况下,线程也非常重要。 最好的例子是 OS 。通常我会编码听我最喜欢的音乐,同时上网等等......现在这就是多线程非常方便的地方,如果只有一个线程,我们就没想到会做我们能做的事情今天做OS。

  4. 跨CPU的多线程用于CPU密集型工作的并行处理

  5. 对于 Java Servlet ,每个请求命中服务器的请求都将由容器提供的单独线程处理。

    < / LI>

答案 5 :(得分:0)

并发在某些算法中也非常有用。例如,我目前正致力于编写一个程序,该程序将使用遗传算法计算复杂问题的最优解。在遗传算法中,你有一群人都必须执行健身功能。这些适应性测试的执行通常将完全相互独立,并且将要执行很多这些测试(例如,您可以拥有数百种人口规模)。并行化可以通过减少执行所有适应度函数所需的时间来显着提高遗传算法的速度。

希望这可以让您了解人们在谈论“cpu密集型”任务时所指的是什么,特别是因为并非所有cpu密集型任务都很容易并行。

答案 6 :(得分:0)

你机器上99.9%的线程没有进行任何CPU密集型工作。我的盒子目前有1084个线程和1%的CPU使用--1084个线程根本没有做任何重要的事情。他们都在等待,很多都来自其他线程的信号,但最重要的是,很多人都在等待I / O.在抢先式多任务操作系统上使用多个线程的最重要和最普遍的原因是提高应用程序的整体I / O性能。这些先发制人的内核迫使我们陷入同步,队列,锁等的痛苦 - 基本上是一个不同的设计区域,其中一条指令不再必然跟随另一条指令。优点是,I / O性能比任何协作调度系统都要好得多,因为任何等待I / O驱动程序的线程都可以在I / O完成时立即“准备/运行”。响应硬件中断的驱动程序。异步I / O不会改变这一点,它只是将I / O等待移动到内核线程池,该内核线程池必须列出异步请求并在发生I / O时使回调设置用户线程就绪,(同时强制用户代码)恢复到显式状态机)。所以'什么类型的问题适合多线程':

1)预期来自多个源的I / O的任何地方都可以异步完成。

2)线程使应用程序设计更容易,更快捷,更安全。如果20个“事物”必须同时发生,那么编写明显的“内联”代码并运行20个线程要比自己开发状态机来处理20个不同的上下文要容易得多。由于进程内的线程共享内存,因此在队列上传递巨大的缓冲区(OK,缓冲区引用/指针),简化分层/流水线应用程序是很简单的。通讯栈。

3)多核盒子上的CPU密集型操作,特别是可以隔离每个线程/核心的数据集以进行缓存优化。

4)AOB:)

没有多线程和抢先内核的I / O性能,就没有BitTorrent,没有视频流,没有MMP游戏,没有AVI播放器。

但是,您可以运行记事本和MS Word ...