java线程池测试,Java线程池【测试Markdown样式】

Java 线程池

目录

重点关注几个问题:

线程池中线程的生命周期

线程池启动后,如何初始化工作线程

线程数如何变化

如何管理空闲的线程

提交任务给工作线程、到工作线程完成任务的过程

线程池内异常处理?

线程池的启动和关闭

ThreadPoolExecutor

概览

线程池解决了什么问题:

执行大量异步任务时性能比较好,通过复用线程池中的线程,来避免创建和销毁线程的开销。

提供管理和限制资源的手段,比如限制线程个数或者动态新增线程。

基于生产者消费者模型

AtomicIntger类型变量ctl表示线程池状态和线程数,最高3位为是状态,低29位是线程个数。

消费者线程封装在内部类Worker中,使用HashSet类型的变量workers保存

Worker

Worker类实现了Runnable和AQS,run()方法调用了ThreadPoolExecutor的runWorker方法。

/**

* Creates with given first task and thread from ThreadFactory.

* @param firstTask the first task (null if none)

*/

Worker(Runnable firstTask) {

setState(-1); // inhibit interrupts until runWorker

this.firstTask = firstTask;

//初始化的时候会将this引用传入工厂方法

this.thread = getThreadFactory().newThread(this);

}

/** Delegates main run loop to outer runWorker. */

public void run() {

runWorker(this);

}

重要的方法

execute

execute(Runnable command)方法,负责提交任务到阻塞队列、并在有必要的情况下添加核心线程或者普通线程。

在线程数小于核心线程数时,添加核心线程addWorder(Runnable firstTask, boolean core);添加成功则返回。

提交任务到阻塞队列、如果提交失败则新增线程、新增线程失败则执行拒绝策略

submit()是用FutureTask封装了Runnable和Callable,然后FutureTask实现了RunnableFuture,所以能够提交给execute()方法

而FutureTask会通过Executors.RunnableAdapter这个适配器类包装Runnable成为Callable,在call()方法调用run()方法,run()方法执行结束后,返回传入的result。

Worker相关

addWorker()方法,负责增加线程数,将新的Worker添加到workers

通过CAS增加线程数,直到增加成功或者检测到线程数达到最大线程数而返回false

增加线程成功后,获取全局锁this.mainLock后线程安全地创建Worker实例,并且调用w.thread.start()启动Worker内部封装的线程开始执行任务。

runWorker()方法,在循环里,获取初始任务或者通过阻塞获取任务,获取任务后在Worker内部锁的保护下执行任务。

若初始任务不为null,则执行;否则,getTask()从阻塞队列中阻塞式获取任务,若返回任务为null则退出循环。

w.lock()在任务执行期间加锁,是为了避免在任务运行期间,其他线程调用shutdown()后正在执行任务的线程被中断(shutdown()只会中断当前被阻塞挂起的线程)

关闭线程池

shutdown()方法,被调用后,线程池不会再接受新的任务、但是队列里面的任务还是会完成。

设置线程池的状态为SHUTDOWN

设置空闲线程的中断标志。

设置中断标志前会尝试获取Worker的内部锁,因此不会中断正在执行任务的线程。

tryTerminate()方法,在满足条件的情况下,设置状态为TERMINATED并唤醒阻塞在termination条件队列的全部线程

SHUTDOWN、无工作线程、工作队列为空

STOP、无工作线程

shutdownNow()方法,线程池不会再接受新的任务,中断正在执行的任务,返回被丢弃的工作任务队列。

直接设置线程池的状态为STOP

中断所有线程。

获取工作队列中的任务并返回。

awaitTermination(long timeout, TimeUnit unit),阻塞调用线程直到线程池状态变为TERMINATED。

状态变为TERMINATED的2种方式:

shutdown()方法,返回前调用tryTerminate()尝试设置状态为TERMINATED

runWorker()方法,当工作线程运行结束后,会调用processWorkerExit()方法,也会调用tryTerminate()方法尝试设置状态为TERMINATED

ScheduledThreadPoolExecutor

可以在指定延迟时间、定时进行任务调度执行的线程池

run()流程

判断是否重复执行的任务

否,则直接调用run()方法。

是,则:

调用FutureTask的runAndReset()方法

setNextRunTime()设置任务下次运行的时间

调用reExecutePeriodic()方法,将任务重新放入——延迟工作队列。

DelayedQueue的take()原理

基于堆实现

先获取锁,进入循环,然后获取堆顶的任务。

如果堆顶任务为空,则在条件队列上等待。

获取任务成功,则判断任务是否到了执行时间。

如果到了,直接出队。

如果时间没到,判断自己是否leader线程。

不是的话,则在条件队列上等待。

是leader线程,则调用awaitNanos()超时自动唤醒。

唤醒后,将leader线程设置为空。

进入下一次循环。

退出循环后,用signal()唤醒等待队列中一个等待的线程,释放锁。

标签:Markdown,Java,队列,Worker,任务,调用,线程,方法

来源: https://www.cnblogs.com/iltonmi/p/14327388.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值