我们要想理解线程池,首先要了解线程池是什么
线程池是一种用于管理和复用线程的技术。在多线程编程中,创建和销毁线程是一项开销较大的操作。而线程池通过预先创建一组线程,并对这些线程进行管理,可以避免频繁地创建和销毁线程,从而提高程序的性能和效率。
举个例子:
在学校附近新开了一家快递店,老板很精明,想到一个与众不同的办法来经营。店里没有雇人,
而是每次有业务来了,就现场找一名同学过来把快递送了,然后解雇同学。这个类比我们平时来
一个任务,起一个线程进行处理的模式。
很快老板发现问题来了,每次招聘 + 解雇同学的成本还是非常高的。老板还是很善于变通的,知
道了为什么大家都要雇人了,所以指定了一个指标,公司业务人员会扩张到 3 个人,但还是随着
业务逐步雇人。于是再有业务来了,老板就看,如果现在公司还没 3 个人,就雇一个人去送快
递,否则只是把业务放到一个本本上,等着 3 个快递人员空闲的时候去处理。这个就是我们要带
出的线程池的模式。
一.线程池的参数介绍
-
核心线程数(Core Pool Size):指定线程池中最小的线程数量,即线程池保持的最低线程数。即使线程池处于空闲状态,也会一直保持这些核心线程。
-
最大线程数(Maximum Pool Size):指定线程池中允许存在的最大线程数量。当核心线程已满且工作队列也已满时,新任务会创建额外的线程,直到达到最大线程数。
-
空闲线程存活时间(Keep Alive Time):指定非核心线程在空闲状态下的最大存活时间。当线程池中的线程数量超过核心线程数,并且空闲时间超过设定的时间时,多余的线程会被销毁。
-
工作队列(Work Queue):用于存储等待执行的任务的数据结构。可以选择不同类型的队列,如无界队列(Unbounded Queue)或有界队列(Bounded Queue)。有界队列在任务数量达到上限时会拒绝新任务的提交。
-
线程工厂(Thread Factory):负责创建新线程的工厂对象。可以自定义线程的创建方式,如设置线程名称、优先级等。
-
拒绝策略(Rejected Execution Policy):当工作队列已满且无法接受新任务时,定义了线程池对新任务的处理方式。常见的策略有抛出异常、丢弃任务、丢弃最旧的任务等。
这些参数可以根据具体的应用场景和性能需求进行调优和配置,以达到最佳的线程池效果。
二,线程池的工作流程一般如下:
-
创建线程池:首先,创建一个线程池对象,并设置线程池的参数,包括核心线程数、最大线程数、空闲线程存活时间、工作队列等。
-
提交任务:当有任务需要执行时,使用线程池对象提交任务。任务可以是实现了某个任务接口的对象或者是一个可执行的任务(Runnable 或 Callable)。
-
判断核心线程是否已满:线程池会先判断当前的活动线程数量是否达到核心线程数。如果没有达到,则创建一个新的线程来执行任务,否则进入下一步。
-
将任务放入工作队列:如果核心线程已满,线程池会将任务放入工作队列中等待执行。工作队列可以是一个无界队列或有界队列,根据具体的实现和配置而定。
-
判断线程池是否已满:如果工作队列已满且线程池中的线程数量还未达到最大线程数,线程池会创建新的线程来执行任务。
-
执行任务:线程池从工作队列中取出一个任务,将其分配给一个空闲的线程来执行。
-
线程执行任务:选中的线程开始执行任务,执行完毕后返回线程池。
-
销毁线程:如果线程空闲时间超过设定的空闲线程存活时间,并且线程池中的线程数量超过核心线程数,多余的线程会被销毁,以释放资源。
-
结束线程池:当不再需要线程池时,可以调用相应的方法来关闭线程池,这将导致线程池停止接受新任务,并且等待已经提交的任务执行完毕。
线程池通过有效地管理和复用线程,提高了程序的性能和效率,减少了线程创建和销毁的开销,并且提供了对线程状态的监控和管理能力。
三,使用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();
}
}