线程池的介绍

发布时间:2024年01月20日

我们要想理解线程池,首先要了解线程池是什么

线程池是一种用于管理和复用线程的技术。在多线程编程中,创建和销毁线程是一项开销较大的操作。而线程池通过预先创建一组线程,并对这些线程进行管理,可以避免频繁地创建和销毁线程,从而提高程序的性能和效率。

举个例子:

在学校附近新开了一家快递店,老板很精明,想到一个与众不同的办法来经营。店里没有雇人,
而是每次有业务来了,就现场找一名同学过来把快递送了,然后解雇同学。这个类比我们平时来
一个任务,起一个线程进行处理的模式。
很快老板发现问题来了,每次招聘 + 解雇同学的成本还是非常高的。老板还是很善于变通的,知
道了为什么大家都要雇人了,所以指定了一个指标,公司业务人员会扩张到 3 个人,但还是随着
业务逐步雇人。于是再有业务来了,老板就看,如果现在公司还没 3 个人,就雇一个人去送快
递,否则只是把业务放到一个本本上,等着 3 个快递人员空闲的时候去处理。这个就是我们要带
出的线程池的模式。

一.线程池的参数介绍

  1. 核心线程数(Core Pool Size):指定线程池中最小的线程数量,即线程池保持的最低线程数。即使线程池处于空闲状态,也会一直保持这些核心线程。

  2. 最大线程数(Maximum Pool Size):指定线程池中允许存在的最大线程数量。当核心线程已满且工作队列也已满时,新任务会创建额外的线程,直到达到最大线程数。

  3. 空闲线程存活时间(Keep Alive Time):指定非核心线程在空闲状态下的最大存活时间。当线程池中的线程数量超过核心线程数,并且空闲时间超过设定的时间时,多余的线程会被销毁。

  4. 工作队列(Work Queue):用于存储等待执行的任务的数据结构。可以选择不同类型的队列,如无界队列(Unbounded Queue)或有界队列(Bounded Queue)。有界队列在任务数量达到上限时会拒绝新任务的提交。

  5. 线程工厂(Thread Factory):负责创建新线程的工厂对象。可以自定义线程的创建方式,如设置线程名称、优先级等。

  6. 拒绝策略(Rejected Execution Policy):当工作队列已满且无法接受新任务时,定义了线程池对新任务的处理方式。常见的策略有抛出异常、丢弃任务、丢弃最旧的任务等。

这些参数可以根据具体的应用场景和性能需求进行调优和配置,以达到最佳的线程池效果。

二,线程池的工作流程一般如下:

  1. 创建线程池:首先,创建一个线程池对象,并设置线程池的参数,包括核心线程数、最大线程数、空闲线程存活时间、工作队列等。

  2. 提交任务:当有任务需要执行时,使用线程池对象提交任务。任务可以是实现了某个任务接口的对象或者是一个可执行的任务(Runnable 或 Callable)。

  3. 判断核心线程是否已满:线程池会先判断当前的活动线程数量是否达到核心线程数。如果没有达到,则创建一个新的线程来执行任务,否则进入下一步。

  4. 将任务放入工作队列:如果核心线程已满,线程池会将任务放入工作队列中等待执行。工作队列可以是一个无界队列或有界队列,根据具体的实现和配置而定。

  5. 判断线程池是否已满:如果工作队列已满且线程池中的线程数量还未达到最大线程数,线程池会创建新的线程来执行任务。

  6. 执行任务:线程池从工作队列中取出一个任务,将其分配给一个空闲的线程来执行。

  7. 线程执行任务:选中的线程开始执行任务,执行完毕后返回线程池。

  8. 销毁线程:如果线程空闲时间超过设定的空闲线程存活时间,并且线程池中的线程数量超过核心线程数,多余的线程会被销毁,以释放资源。

  9. 结束线程池:当不再需要线程池时,可以调用相应的方法来关闭线程池,这将导致线程池停止接受新任务,并且等待已经提交的任务执行完毕。

线程池通过有效地管理和复用线程,提高了程序的性能和效率,减少了线程创建和销毁的开销,并且提供了对线程状态的监控和管理能力。

三,使用Executors 创建常见的线程池



import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class threadDemo21 {
    public static void main(String[] args) {
        // 创建固定大小的线程池,线程数量为 5
        ExecutorService executor = Executors.newFixedThreadPool(5);

        // 提交任务到线程池
        for (int i = 0; i < 10; i++) {
            final int taskNumber = i;
            executor.execute(new Runnable() {
                public void run() {
                    System.out.println("Task " + taskNumber + " is being executed.");
                    try {
                        // 模拟任务执行时间
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Task " + taskNumber + " has finished executing.");
                }
            });
        }

        // 关闭线程池
        executor.shutdown();
    }
}

文章来源:https://blog.csdn.net/m0_62787283/article/details/135601474
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。