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中的线程池有啥用?的主要内容,如果未能解决你的问题,请参考以下文章

java io学习 线程池

java所提供的线程池有几种之线程池总结

线程池有这么多细节,你都了解么?

Java常见的线程池有哪些?

Java常见的线程池有哪些?

java 线程池有哪几种,各有什么特点