Java中的线程池有啥用?
Posted
技术标签:
【中文标题】Java中的线程池有啥用?【英文标题】:What is the use of a Thread pool in Java?Java中的线程池有什么用? 【发布时间】:2011-03-18 05:30:00 【问题描述】:线程池有什么用?有没有一个很好的现实世界的例子?
【问题讨论】:
tutorials.jenkov.com/java-concurrency/thread-pools.html 【参考方案1】:线程池是一组最初创建的等待作业并执行它们的线程。这个想法是让线程始终存在,这样我们就不必每次都为创建它们而付出额外的时间。当我们知道有要处理的作业流时,它们是合适的,即使有时可能没有作业。
这是来自Wikipedia 的漂亮图表:
【讨论】:
我们可以估计线程池所需的线程数吗?还是每个线程池有线程限制?【参考方案2】:Java 教程中的Thread Pools 有一个很好的概述:
使用工作线程可以最大限度地减少由于创建线程而产生的开销。线程对象使用大量内存,在大型应用程序中,分配和释放许多线程对象会产生大量内存管理开销。
【讨论】:
【参考方案3】:简单的Google 搜索将获得有关 Java 线程池和一般线程池的大量信息。
这里有一些有用的链接:
http://docs.oracle.com/javase/tutorial/essential/concurrency/pools.html
http://en.wikipedia.org/wiki/Thread_pool_pattern
【讨论】:
感谢您的提示。希望这是一个更合适的答案。 不客气,这已经更好了(之前的评论已删除)。不过,我建议阅读How to deal with google questions?、Is it bad to ask google searchable questions on Stack Overflow 和Is it appropriate to ask questions on Stack Overflow without prior research?。 是的...抱歉,回答有点滑稽。现在是清晨,咖啡还没有开始。也感谢您的链接。【参考方案4】:线程池是一个已经创建的工作线程池,准备好完成这项工作。它创建Thread
并管理它们。线程池不是创建线程并在任务完成后丢弃它们,而是以工作线程的形式重用线程。
为什么?
因为创建线程是一个耗时的过程,它会延迟请求处理。它还根据每个 JVM 允许的线程数来限制客户端的数量,这显然是一个有限的数量。
使用 Executor 框架创建固定大小的线程池 -
Java 5 引入了一个全功能的内置线程池框架,通常称为 Executor 框架。
使用 Java 5 Executor
框架创建固定大小的线程池非常容易,因为 Executors
类提供了静态工厂方法。您需要做的就是定义要同时执行的任务,然后将该任务提交给ExecutorService
。
从这里开始,线程池将负责如何执行该任务;它可以由任何空闲的工作线程执行。
public class ThreadPoolExample
public static void main(String args[])
ExecutorService service = Executors.newFixedThreadPool(10); //create 10 worker threads in Thread Pool
for (int i =0; i<100; i++)
service.submit(new Task(i)); //submit that to be done
final class Task implements Runnable
private int taskId;
public Task(int id)
this.taskId = id;
@Override
public void run()
System.out.println("Task ID : " + this.taskId +" performed by "
+ Thread.currentThread().getName());
Output:
Task ID : 0 performed by pool-1-thread-1
Task ID : 3 performed by pool-1-thread-4
Task ID : 2 performed by pool-1-thread-3
Task ID : 1 performed by pool-1-thread-2
Task ID : 5 performed by pool-1-thread-6
Task ID : 4 performed by pool-1-thread-5
*Output may vary from system to system
【讨论】:
【参考方案5】:线程池仅在无法确定/预测客户端请求的数量/发生率的服务器-客户端情况下有用。
在这种情况下,每次客户端请求创建一个新线程有两个缺点:
1) 线程创建的运行时延迟: 创建线程需要一些时间,因此实际作业不会在请求到来时立即启动。客户端可能会注意到轻微的延迟。
此标准在客户期望立即采取行动的交互式系统中至关重要。
2) 不受控制地使用系统资源: 线程会消耗系统资源(内存等),因此如果出现前所未有的客户端请求流,系统可能会耗尽资源。
线程池通过以下方式解决上述问题: 1) 在服务器启动时创建指定数量的线程,而不是在运行时创建它们。 2) 限制在任何给定时间运行的线程数。
注意:以上适用于固定大小的线程池。
【讨论】:
In this scenario...
是指哪种场景?
有客户端向服务器程序提交请求的场景。而且,无法预测客户端请求的时间/数量......希望有所帮助。
@AvinashGanta 我们如何估计在线程池中创建所需的线程?
对此我没有一个通用的答案。但是,线程池的大小将取决于: 1)客户端请求的频率:更频繁的请求(需要)池中的更多线程。 2)服务器和客户端之间商定的 SLA,它指定服务器可以开始对请求采取行动的最长时间:更严格的 SLA(要求)池中的更多线程。 3)可用的系统资源:系统资源会限制池中可以创建的最大线程数。【参考方案6】:
您可以假设线程是实际的工作人员,而线程池是一组工作人员。 您可以出于各种原因(如优先级、目的等)创建多个组。 因此,虽然一个池可能用于后台调度、电子邮件广播等通用任务,但可能有一个事务处理池来同时处理多个事务。对于 Executor Service,我相信您不希望在其他非关键活动(如广播确认电子邮件或数据库维护活动)未完成后延迟交易作业的完成。 您可以将它们隔离到池中并独立维护它们。 这是一个非常简单的答案,无需涉及技术术语。 问候, 韩泰
【讨论】:
【参考方案7】:已经有很好的答案可以解释它,但让我们理解它 举个例子:
没有线程池的问题:考虑一个 Web 服务器应用程序,其中每个 HTTP 请求都由一个单独的线程处理。如果应用程序只是为每个新的 HTTP 请求创建一个新线程,并且系统接收到的请求超出了它可以立即处理的数量,那么当所有这些线程的开销超过系统的容量时,应用程序将突然停止响应所有请求。
使用线程池的解决方案:由于可以创建的线程数有限制,应用程序不会像 HTTP 请求一样快地为它们提供服务,但它会为它们提供服务系统可以维持的最快速度。
更多详情(所有线程的开销):Why is creating a Thread said to be expensive?
【讨论】:
以上是关于Java中的线程池有啥用?的主要内容,如果未能解决你的问题,请参考以下文章