有人能用例子解释我们为什么要使用线程池吗。
从理论上讲,我已经知道线程池与执行程序的使用。
我已经看了很多教程,但我没有得到任何关于我们为什么要使用Threadpools的实际例子,它可以是newFixedThreadPool或newCachedThreadPool或newSingleThreadExecutor
在可扩展性和性能方面。
如果有人用有关性能和可伸缩性的例子来解释我的话?
首先,查看我昨天写的线程池的描述:Android线程池来管理多个蓝牙切换线程?(好吧,这是关于android的,但对于经典的java也是一样的)。
我似乎总是发现使用线程池的主要用途是非常好地管理一个非常常见的问题:生产者-消费者。在这种模式中,有人需要不断地发送工作项(生产者),由其他人(消费者)处理。工作项是从某种类似流的源获得的,如套接字、数据库或磁盘文件的集合,需要多个工作者才能有效处理。此处可识别的主要组件有:
- 生产者:一个不断发布作业的线程
- 发布作业的队列
- 使用者:从队列中获取作业并执行它们的工作线程
除此之外,还需要使用同步来使所有这些工作正常进行,因为在没有同步的情况下读取和写入队列可能会导致数据损坏和不一致。此外,我们需要使系统高效,因为消费者不应该在无事可做时浪费CPU周期
现在这种模式非常常见,但要从头开始实现它需要付出相当大的努力,这很容易出错,需要仔细审查。
解决方案是线程池。它非常方便地管理工作队列、使用者线程和所有需要的同步。你所需要做的就是扮演生产者的角色,并为池提供任务!
我会从一个问题开始,然后尝试找到解决方案。
如果你以现有的方式开始,你可以找到一个解决方案来寻找要解决的问题,而且你很可能会不恰当地使用它。
如果你想不出线程池的用途,就不要使用它们。;)
人们常犯的一个错误是认为,因为他们现在有很多cpu,所以他们必须把它们都用起来,就好像这本身就是一个原因一样。这就像说我有很多磁盘空间,我必须找到一种方法来使用所有的空间
使用线程池的一个很好的理由是提高CPU边界进程的性能和IO边界进程的简单性(而不是使用一个线程的非阻塞IO)
如果您有一个繁忙的CPU绑定进程,它执行可以独立执行的任务,那么线程池就有一个很好的用例。
注意:线程池通常只有一个线程。这些有特定的静态工厂。如果你想要一个简单的后台工作人员,这可能是一个选择。
注意2:一个常见的错误是认为一个CPU绑定的任务将在数百或数千个线程上运行得最好。线程的优化数量可以是您拥有的核心或cpu的数量。一旦所有这些都很忙,您可能会发现额外的线程只是增加了开销。
线程池用于通过重用已经创建的线程来避免这种成本。因此,使用线程池可以获得比每次创建新线程更好的性能。
还要注意,创建的线程在使用后可能需要"删除",这会增加垃圾收集的成本和发生垃圾收集的频率(因为内存填充得更快)。
此分析只是从性能的角度进行的。目前,我想不出使用线程池在可伸缩性方面有什么优势。
我在谷歌上搜索了"为什么使用java线程池",发现:
线程池为线程问题提供了解决方案生命周期开销和资源颠簸问题。
http://www.ibm.com/developerworks/library/j-jtp0730/index.html
和
newCachedThreadPool方法创建一个具有可扩展线程池。此执行器适用于启动的应用程序许多短命的任务。newSingleThreadExecutor方法创建一次执行单个任务的执行器。
http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html