线程池的理解和运用

什么是线程池?

线程池是一种基于池化技术的并发执行模型,用于在多线程编程中有效管理线程的创建、执行、和销毁过程。线程池的核心思想是预先创建一定数量的线程,放入一个池中备用,当有新的任务到来时,就从池中取出一个线程来执行任务,执行完毕后,线程不会被销毁,而是返回线程池中等待下一次任务。

使用线程池的好处包括:

  1. 降低资源消耗:重复利用已经创建的线程,避免了频繁创建和销毁线程的开销,从而提高系统资源的利用率。
  2. 提高响应速度:任务到来时,无需等待线程创建即可立即执行,因此可以减少任务的响应时间。
  3. 提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性。线程池可以统一分配、调优和监控线程。
  4. 提供更多灵活和强大的功能:如线程池可以根据系统的负载自动调整线程池中线程的数量,实现动态管理。

线程池通常包含几个关键组成部分:

  • 线程池管理器(Pool Manager):用于创建和管理线程池。
  • 工作队列(Work Queue):未处理任务的缓存队列,任务在等待被线程池中的线程执行。
  • 工作线程(Worker Threads):线程池中的线程。
  • 任务接口(Task Interface):每个任务必须实现的接口,以便工作线程可以执行任务。

在Java中,Executor框架是管理线程池的一种高级实现,提供了各种类型的线程池,如FixedThreadPoolCachedThreadPoolSingleThreadExecutor等,让开发者可以根据实际需求选择最适合的线程池来使用。

线程池的相关接口和实现类

java中常用Executors工具类,来创建常见的线程池。

常见的四种线程池对象

  1. Executors.newCachedThreadPool():动态数量的ThreadPoolExecutor线程池对象,线程在存活时间内(60秒)可以重复使用,这个线程池没有核心线程数,同时它的工作队列也是不存放线程任务的

  2. Excutors.newFixedThreadPool():固定数量的ThreadPoolExecutor线程池对象,该线程池的最大线程数和核心线程数相同

  3. Excutors.newSingleThreadExecutor():这是一个只有一个线程的ThreadPoolExecutor线程池对象

  4. Executors.newScheduledThreadPool():这是一个任务调度线程池的ScheduledThreadPoolExecutor线程池对象,因为这个线程池是ScheduledThreadPoolExecutor接口的实现类,所有在实现任务调度上有三种方法:

    当使用schedule()方法延迟指定时间后执行线程任务(仅执行一次)。

    当使用scheduleAtFixedRate()方法会延迟指定时间后执行线程任务,并且每过指定时间执行一次。

    当使用scheduleWithFixedDelay()()方法会延迟指定时间后执行线程任务,并会在上一次任务执行结束后,"延迟"时间后执行

ExecutorService在提交线程任务时的两种方法:

  1. 通过execute运行Runnable接口接口没有返回值类型
  2. 通过submit运行Callable接口也可以运行Runnable接口

ExecutorService关闭线程池的两种方法:

  1. shutdown():已提交的任务将继续执行,但不再接收新的任务
  2. shutdownNow():终止所有正在执行的任务,并停止处理等待队列中的的任务

在这里插入图片描述

线程池的执行流程

在这里插入图片描述

如图所示,就是线程池的工作流程,可以分为五个步骤:

  1. 当有线程任务提交到线程池时,线程池会判断当前线程池中是否有空闲线程,如果存在空闲线程会优先分配空闲线程执行线程任务
  2. 当线程池中不存在空闲线程时,会判断当前线程池中的线程数是否小于核心线程数,如果小于核心线程数时会创建核心线程,并执行线程任务
  3. 如果当前线程数大于核心线程数时,线程池会判断当前线程池的工作队列是否已满,如果工作队列未满,会将线程任务加入到工作队列中,当线程池中存在空闲线程时,会按照先进先出的原则依次取出线程任务
  4. 当线程池的工作队列已满时,会判断当前线程池的最大线程数是否超出,未超出会创建非核心线程,并执行线程任务,当线程任务结束后,非核心线程会被回收
  5. 当当前线程池的线程数到达最大线程数时,会执行拒绝策略

常用的四种线程池及其特点

public class Test06 {
	public static void main(String[] args) {
		
		//创建ThreadPoolExecutor的线程池
		//特点:线程池的数量是动态数量(线程会被缓存,空闲线程超过六十秒会被回收)
		Executors.newCachedThreadPool();
		
		//创建ThreadPoolExecutor的线程池
		//特点:线程池的数量是固定的
		Executors.newFixedThreadPool(10);
		
		//创建ThreadPoolExecutor的线程池
		//只有一个线程的线程池
		Executors.newSingleThreadExecutor();
		
		//创建ScheduledThreadPoolExecutor的线程池
		// 这个线程池的工作队列是DelayedWorkQueue
		Executors.newScheduledThreadPool(1);
	}
}

线程池的核心配置参数

在这里插入图片描述

如上图所示就是我们在定义线程池是需要配置的核心参数:

  • int corePoolSize:核心线程数(也叫最小线程数)

  • int maximumPoolSize:最大线程数

  • long keepAliveTime:非核心线程的存活时间

  • TimeUnit unit:存活时间的单位

  • BlockingQueue workQueue:工作队列(阻塞队列,线程安全的队列集合)

  • ThreadFactory threadFactory:线程工厂

  • RejectedExecutionHandler handler:拒绝策略

    四种拒绝策略:

    AbortPolicy:丢弃当前线程任务,并抛出异常

    DiscardPolicy:丢弃当前线程任务,但不抛出异常

    DiscardOldestPolicy:丢弃工作队列中最“老”的线程任务

    CallerRunsPolicy:直接由“当前调用线程”执行该线程任务

    或者自定义拒绝策略:实现RejectedExecutionHandler接口

线程池的状态

在线程池被创建后,线程池处于运行状态,接受新的线程任务,并处理工作队列中的线程任务,当线程池调用shutdown()方法后,线程池变为关闭状态,此状态下的线程池不接受新的线程任务,但仍处理工作队列中的任务,当线程池调用shutdownNow()方法后,线程池变为停止状态,此状态下的线程池不接收新任务,也不处理工作队列中的任务,同时中断正在执行的任务,当所有任务已经结束,工作队列中的任务数量为0时,线程池变为整理状态,当线程池彻底关闭,线程池变为终止状态

线程池的状态:

  • RUNNING(运行状态):允许新任务,并处理工作队列中的任务,可以调用shutdown()方法和shutdownNow()方法
  • SHUTDOWN(关闭状态):不接收新任务,但仍处理工作队列中的任务
  • STOP(停止状态):不接收新任务,也不处理工作队列中的任务,同时中断正在执行的任务
  • TIDYING(整理状态):所有任务已经结束,工作队列中的任务数量为0
  • TERMINATED(终止状态):线程池彻底关闭

线程池如何保存状态和线程数量:AtomicInteger ctl:前3位保存“线程状态”,后29位保存“线程数量(线程池存活线程数)”

  • 15
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值