详解Java线程池的使用及工作原理

网友投稿 257 2022-10-22


详解Java线程池的使用及工作原理

一、什么是线程池?

线程池是一种用于实现计算机程序并发执行的软件设计模式。线程池维护多个线程,等待由调度程序分配任务以并发执行,该模型提高了性能,并避免了由于为短期任务频繁创建和销毁线程而导致的执行延迟。

二、线程池要解决什么问题?

说到线程池就一定要从线程的生命周期讲起。

从图中可以了解无论任务执行多久,每个线程都要经历从生到死的状态。而使用线程池就是为了避免线程的重复创建,从而节省了线程的New至Runnable, Running至Terminated的时间;同时也会复用线程,最小化的节省系统资源,于此同时提高了响应速度。

三、线程池的使用

线程池的创建

使用ThreadPoolExecutor并配置7个参数完成线程池的创建

public ThreadPoolExecutor(int corePoolSize,

int maximumhttp://PoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueue workQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler)

corePoolSize:线程池中核心线程的最大值

maximumPoolSize:线程池中最大线程数

keepAliveTime:非核心线程空闲的存活时间大小

unit:keepAliveTime的单位,常用的有秒、分钟、小时等

workQueue:阻塞队列类型

threadFactory:线程工厂,用于配置线程的名称,是否为守护线程等

handler:线程池的拒绝策略

四、常用阻塞队列

ArrayBlockingQueue

底层基于数组的实现的有界阻塞队列

LinkedBlockingQueue

底层基于单链表的阻塞队列,可配置容量,不配置容量默认为Integer.MAX_VALUE

五、线程工厂

在《阿里巴巴java开发手册》中强制要求指定线程的名称

由于工作是使用hutool比较多,里面也包含对ThreadFactory的封装,可以很方便的指定名称

ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();

六、拒绝策略

当线程池内工作线程数大于maximumPoolSize时,线程就不再接受任务,执行对应的拒绝策略;目前支持的拒绝策略有四种:

1.AbortPolicy(默认):丢弃任务并抛出RejectedExecutionException异常

2.CallerRunsPolicy:由调用者处理

3.DiscardOldestPolicy:丢弃队列中最前面的任务,并重新入队列

4.DiscardPolicy:丢弃任务但不抛出异常

七、线程池的执行逻辑

// 创建线程工厂

ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();

// 创建线程池

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), http://threadFactory, new ThreadPoolExecutor.AbortPolicy());

八、execute()方法

// 组合值;保存了线程池的工作状态和工作线程数

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

public void execute(Runnable command) {

// 任务为空 抛出NPE

if (command == null)

throw new NullPointerException();

// 获取线程池状态

int c = ctl.get();

// 如果工作线程数小于核心线程数就创建新线程

if (workerCountOf(c) < corePoolSize) {

if (addWorker(command, true))

return;

c = ctl.get();

}

// 如果线程池处于Running状态,就把任务放在队列尾部

if (isRunning(c) && workQueue.offer(command)) {

// 重新检查线程池状态

int recheck = ctl.get();

// 如果线程池不是Running状态,就移除刚才添加的任务,并执行拒绝策略

if (! isRunning(recheck) && remove(command))

reject(command);

// 是Running状态,就添加线程

else if (workerCountOf(recheck) == 0)

addWorker(null, false);

}

// 添加任务失败,执行拒绝策略

else if (!addWorker(command, false))

reject(command);

}

// addWorker()完成线程的创建

九、执行流程


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:工业富联市值缩水超2500亿,富士康的工业互联网咋样了?
下一篇:外网主机如何将数据包发送到共用一个公网IP的局域网某特定主机上的
相关文章

 发表评论

暂时没有评论,来抢沙发吧~