多线程与高并发9-线程池2

Executors线程池工厂(ThreadPoolExecutor)

newSingleThreadPool();
单线程池,保证任务按顺序执行。线程池封装了任务队列及线程池声明周期。底层使用LinkedBlockingQueue,最大值Integer.MAX_VALUE,阿里开发者手册不推荐使用jdk提供的线程池,无拒绝策略。

newCachedThreadPool();
核心线程数为0,最大线程数是Integer.MAX_VALUE,任务队列是SynchronousQueue。
有任务就新建一个线程

newFixedThreadPool();
定长线程数线程池,通过传参,核心线程数和最大线程数的值一致。但是也是用的LinkedBlockingQueue。

(在保证任务不堆积的情况下,任务数量忽高忽低使用Cached,任务数量比较平稳使用Fixed,Fixed是并行执行,效率较高)

newScheduledThreadPool();
定时执行任务。线程最大值为Integer.MAX_VALUE,使用Delay延时队列。
(定时框架:Quartz,cron)

ForkJoinPool

newWorkStealingPool(); (底层封装的ForkJoinPool)

每一个线程有自己的单独的队列。如果当前队列为空,回去其他队列中去偷线程放到自己的队列中。

对比ThreadPoolExecutor,是线程去任务队列中去拿任务。
而ForkJoinPool每一个线程都维护着自己的任务队列,当线程本身的任务队列里面空了,会通过work stealing算法(加锁),去其他线程的任务队列中拿一个来执行。进行了任务的拆分(Fork过程)

ForkJoinPool会在执行完之后,(Join过程)最后汇总到父任务,最后汇总到根任务

//ForkJoinPool执行需要继承
static class AddTask extends RecursiveAction//无返回值
static class AddTaskRet extends RecursiveTask<Long>//有返回值

ParalleStreamAPI

并行处理api,底层也是使用ForkJoinPool

List<Integer> nums = new ArrayList<>();
		Random r = new Random();
		for(int i=0; i<10000; i++) nums.add(1000000 + r.nextInt(1000000));
		
nums.parallelStream().forEach(ParallelStreamAPI::doSomeThing);

线程池大小

线程池大小和处理器的利用率之比可以使用下面的公式估算:
N threads = N cpu * U cpu * (1+W/C)
Ncpu是处理器的核的数目,可以通过

Runtime.getRuntime().availableProcessors()

Ucup是期望的CPU利用率(介于0-1之间)
W/C是等待时间与计算时间的比率(wait,computation)[一个线程有多长时间让出CPU,有多长时间使用CPU]

Concurrent、Parallel

并发:任务提交
并行:任务执行
并行是并发的子集

线程池状态

RUNNING:执行
SHUTDOWN:停止
STOP:马上要求停止
TIDYING:SHUTDOWN完毕,正在整理
TERMINATE:线程完全结束

线程池execute()执行顺序

先创建核心线程,核心线程满载装载到队列,队列满载尝试再次申请线程,如果失败,执行拒绝策略。

addWorker(),线程数数量+1,真正的addWorker(),最后start()

发布了25 篇原创文章 · 获赞 0 · 访问量 578

猜你喜欢

转载自blog.csdn.net/RaymondCoder/article/details/105139058
今日推荐