【问题标题】:What is the use of a Thread pool in Java?Java中的线程池有什么用?
【发布时间】:2011-03-18 05:30:00
【问题描述】:

线程池有什么用?有没有一个很好的现实世界的例子?

【问题讨论】:

标签: java multithreading threadpool


【解决方案1】:

线程池是一组最初创建的等待作业并执行它们的线程。这个想法是让线程始终存在,这样我们就不必每次都为创建它们而付出额外的时间。当我们知道有要处理的作业流时,它们是合适的,即使有时可能没有作业。

这是来自Wikipedia 的漂亮图表:

【讨论】:

  • 我们可以估计线程池所需的线程数吗?还是每个线程池有线程限制?
【解决方案2】:

Java 教程中的Thread Pools 有一个很好的概述:

使用工作线程可以最大限度地减少由于创建线程而产生的开销。线程对象使用大量内存,在大型应用程序中,分配和释放许多线程对象会产生大量内存管理开销。

【讨论】:

    【解决方案3】:

    简单的Google 搜索将获得有关 Java 线程池和一般线程池的大量信息。

    这里有一些有用的链接:

    【讨论】:

    【解决方案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?

        【讨论】:

          猜你喜欢
          • 2022-01-10
          • 2012-05-08
          • 2015-02-13
          • 2010-11-14
          • 1970-01-01
          • 2010-11-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多