线程池的常用接口实现及执行流程

本文详细介绍了Java线程池的核心概念,包括ExecutorService接口、ThreadPoolExecutor的实现、Executors工具类创建的常见线程池类型,以及线程池参数、拒绝策略、执行流程和状态管理。重点探讨了线程池的工作原理和核心概念,有助于理解线程池在并发编程中的作用。
摘要由CSDN通过智能技术生成

线程池

线程池接口

在这里插入图片描述

ExecutorService

访问操作线程池,继承Executor接口。

ThreadPoolExecutor及其子类

线程池的具体实现,实现了AbstractThreadPoolExecutor抽象类。

Executors工具类 (封装了常用线程池的创建)

根据设定参数的不同,可以分为下面四种常用的线程池对象:

动态数目线程池对象(ThreadPoolExecutor)

线程在存活时间内(60秒)可以重复使用

Executors.newCachedThreadPool();
固定数目线程池对象(ThreadPoolExecutor)
Executors.newFixedThreadPool(20);
单个线程池对象(ThreadPoolExecutor)
Executors.newSingleThreadExecutor();
任务调度线程池对象(ScheduledThreadPoolExecutor)
Executors.newScheduledThreadPool(20);

提交调度线程任务

  • schedule() 指定延迟时间后,执行线程任务1次
  • scheduleAtFixedRate() 固定的时间间隔,触发执行线程任务
  • scheduleWithFixedDelay() 上一次任务执行结束后,"延迟"时间后执行

线程池参数

1、corePoolSize:核心线程数,线程池中最少线程,核心线程不会被回收。

2、maximumPoolSize:最大线程数,线程池中最多线程,包含核心线程数,不能小于核心线程数。

3、keepAliveTime:非核心线程(除去核心线程之外的线程)存活时间,如果非核心线程的空闲时间大于此参数,将会被回收。

4、TimeUnit:时间单位,参数keepAliveTime的时间单位。

5、BlockingQueue:阻塞工作队列,当来一个新的线程任务时,如果当前没有空闲线程,此线程任务将会进入阻塞工作队列中进行等待。

6、ThreadFactory:线程工厂,用于创建线程,自定义线程的名称。(需要实现ThreadFactory接口,实现newThread()方法,在此方法中,新建Thread对象,通过调用setName()方法给线程定义名称。)

class MyThreadFactory implements ThreadFactory{
	
	public AtomicInteger threadNumber = new AtomicInteger();
	public String preFix;
	
	public MyThreadFactory(String preFix) {
		this.preFix = preFix;
	}

	@Override
	public Thread newThread(Runnable r) {
		Thread t =  new Thread(r,preFix + threadNumber.getAndIncrement());
		
		if(t.isDaemon()) {
			t.setDaemon(false);
			
		}
		if(t.getPriority() != Thread.NORM_PRIORITY) {
			t.setPriority(Thread.NORM_PRIORITY);
		}
		return t;
	}
}

7、RejectedExecutionHandler:拒绝策略,当线程池中没有空闲线程,且阻塞工作队列已满,且最大线程数也已超出,此时再来线程任务将执行拒绝策略。

四种拒绝策略

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

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

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

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

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

线程池的执行流程

在这里插入图片描述

首先,通过execute()或者submit()提交线程任务到线程池中,然后由线程池判断是否可以执行,反之执行拒绝策略。

在这里插入图片描述

如上图所示,就是线程池的执行过程,可以分为五个主要步骤:

1.提交任务后会首先进行判断是否存在空闲线程,如果存在直接执行线程任务。

2.若果当前工作线程数与核心线程数的比较,如果当前工作线程数小于核心线程数,则直接调用 addWorker() 方法创建一个核心线程去执行任务;

3.如果工作线程数大于核心线程数,即线程池核心线程数已满,则新任务会被添加到阻塞队列中等待执行,当然,添加队列之前也会进行队列是否为空的判断;

4.如果线程池里面存活的线程数已经等于核心线程数了,且阻塞队列已经满了,再会去判断当前线程数是否已经达到最大线程数 maximumPoolSize,如果没有达到,则会调用 addWorker() 方法创建一个非核心线程去执行任务;

5.如果当前线程的数量已经达到了最大线程数时,当有新的任务提交过来时,会执行拒绝策略

总结来说就是优先核心线程、阻塞队列次之,最后非核心线程。

线程池的状态

RUNNING 运行状态

允许新任务,并处理工作队列中的任务

  • 调用shutdown()方法 ,进入关闭状态
  • 调用shutdownNow() /stop()方法,进入停止状态
SHUTDOWN 关闭状态

不接收新任务,但仍处理工作队列中的任务

STOP 停止状态

不接收新任务,也不处理工作队列中的任务,同时中断正在执行的任务

TIDYING 整理状态

所有任务已经结束,工作队列中的任务数量为0

TERMINATED 终止状态

线程池彻底关闭

在这里插入图片描述

线程池如何保存状态和线程数量

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

在这里插入图片描述

  • 9
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值