浅谈线程池

Posted 小写丶H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈线程池相关的知识,希望对你有一定的参考价值。

线程池

线程池的使用场景

在方法中直接new一个线程,当如果频繁的调用这个方法,那么就会创建很多线程,这样不仅会消耗系统资源,还会降低系统的稳定性,极其容易搞崩服务器。所以就需要用到线程池

线程池的好处

1.响应速度的提高(任务不需要等待线程的创建,可以直接执行)
2.系统资源消耗降低(重复利用已经创建的线程)
3.线程的可管理性(使用线程池进行统一分配,调优和监控)

线程池的创建

这是几个java自带的功能线程池,已经封装好的,可以直接使用的。
1.可缓存线程池(CachedThreadPool)
2.定长线程池(FixedThreadPool)
3.定时线程池(ScheduledThreadPool )
4.单线程化线程池(SingleThreadExecutor)
5.可以窃取的线程池(WorkStealingPool)

ExecutorService threadPool = null;
threadPool = Executors.newCachedThreadPool();
//有缓冲的线程池,线程数 JVM 控制
threadPool = Executors.newFixedThreadPool(3);
//固定大小的线程池
threadPool = Executors.newScheduledThreadPool(2);
//定时线程池
threadPool = Executors.newSingleThreadExecutor();
//单线程的线程池,只有一个线程在工作
threadPool = Executors.newWorkStealingPool();
//JDK 1.8 新增,用于创建一个可以窃取的线程池,底层使用 ForkJoinPool 实现。

线程池的七个参数

threadPool = new ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) 
//默认线程池,可控制参数比较多  



1.corePoolSize(必需):核心线程数。默认情况下,核心线程会一直存活,但是当将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。
2.maximumPoolSize(必需):线程池所能容纳的最大线程数。当活跃线程数达到该数值后,后续的新任务将会阻塞。
3.keepAliveTime(必需):线程闲置超时时长。如果超过该时长,非核心线程就会被回收。如果将 allowCoreThreadTimeout 设置为 true 时,核心线程也会超时回收。
4.unit(必需):指定 keepAliveTime 参数的时间单位。常用的有:TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)、TimeUnit.MINUTES(分)。
5.workQueue(必需):任务队列。通过线程池的 execute() 方法提交的 Runnable 对象将存储在该参数中。其采用阻塞队列实现。
6.threadFactory(可选):线程工厂。用于指定为线程池创建新线程的方式。
7.handler(可选):拒绝策略。当达到最大线程数时需要执行的饱和策略。

拒绝策略(四种)

RejectedExecutionHandler rejected = null;
rejected = new ThreadPoolExecutor.AbortPolicy();
//默认,队列满了丢任务抛出异常
rejected = new ThreadPoolExecutor.DiscardPolicy();
//队列满了丢任务不抛异常
rejected = new ThreadPoolExecutor.DiscardOldestPolicy();
//将最早进入队列的任务删,之后再尝试加入队列
rejected = new ThreadPoolExecutor.CallerRunsPolicy();
//如果添加到线程池失败,那么主线程会自己去执行该任务;
//如果执行程序已关闭(主线程运行结束),则会丢弃该任务

ThreadPoolExecutor.AbortPolicy:(默认)丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

举例

如果核心线程数为5,最大线程数6,任务队列数为10,现在一次提交20个任务会是一个怎样的过程?
答:首先我们得知道线程池的工作顺序为:corePoolSize -> 任务队列 -> maximumPoolSize -> 拒绝策略
.所以,第一个任务到来,创建第一个核心线程,前5个任务放到5个核心线程上;
.然后第6个任务放到队列上,也就是6至16的任务放到队列中;
.因为最大线程数为6,所以第16个任务放到创建的普通线程上;
.当第17个任务的时候,就会触发拒绝策略,策略的具体可以我们来定(1.丢任务,报异常;2.丢任务,不报异常;3.删除掉队列中的旧任务,然后加到队列中;4.添加新的线程,处理新任务,添加失败那么核心线程会去处理,如果核心线程关闭,那么,丢任务)。

以上是关于浅谈线程池的主要内容,如果未能解决你的问题,请参考以下文章

浅谈线程池

浅谈线程池

浅谈线程池

浅谈线程池(中):独立线程池的作用及IO线程池

浅谈ThreadPoolExecutor线程池底层源码

C++并发与多线程 13_线程池浅谈,线程数量总结