线程池
池化技术
程序运行的本质:占用系统的资源,优化资源的使用 => 线程池,JDBC连接池,内存池,对象池
事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我
- 最小连接数
- 最大连接数
线程池的好处?
- 减低资源消耗
- 提高响应效率(创建和销毁十分浪费资源)
- 方便管理
线程可以复用,可以控制最大并发数,管理线程
线程池:三大方法,七大参数,四种拒绝策略
阿里巴巴多线程规约:线程不允许使用Executors创建,而是通过ThreadPoolExecutor的方式,这种处理方式让写的同学更加明确线程池的运行规则,避免资源耗尽的风险
三大方法
public class Demo01 {
public static void main(String[] args) {
//Executors 一个工具类,三大方法
//ExecutorService threadPool = Executors.newSingleThreadExecutor();//创建一个单个线程数的线程池
//ExecutorService threadPool = Executors.newFixedThreadPool(5); //创建一个固定线程数的线程池
ExecutorService threadPool = Executors.newCachedThreadPool(); //遇强则强,遇弱则弱
try {
for (int i = 0; i < 100; i++) {
// new Thread().start(); 传统方式
//使用线程池创建
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//程序结束需要关闭线程池
threadPool.shutdown();
}
}
}
源码分析
public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory);
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
七大参数
本质
public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
int maximumPoolSize, //最大线程池大小(候客区以及核心线程池都没有空闲位置时,开启所有线程)
long keepAliveTime, //存活时间,线程池中多余线程(除了核心线程池之外的线程)超时无人调用就会释放
TimeUnit unit, //超时单位
BlockingQueue<Runnable> workQueue, //阻塞队列(候客区,当核心线程池满了之后,多于请求存放在这里)
ThreadFactory threadFactory, //线程工厂(创建线程的一般不用动)
RejectedExecutionHandler handler) //拒绝策略 当候客区(阻塞队列)已满 而且 已达最大线程并发量时拒绝先来的请求 {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.acc = System.getSecurityManager() == null ?
null :
AccessController.getContext();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
四种拒绝策略(当候客区(阻塞队列)已满 而且 已达最大线程并发量时拒绝先来的请求)
默认拒绝策略
- AbortPolicy():默认拒绝策略 线程满了,阻塞队列满了,做不处理处理方式,并且抛出异常
- CallerRunsPolicy(): 哪里来的去哪里 main ok
- DiscardPolicy():队列满了不会抛出异常,会丢掉任务
- DiscardOldestPolicy():队列满了会尝试去和第一个使用线程的竞争,如果竞争不过则会丢掉任务
public class Demo02 {
public static void main(String[] args) {
//自定义线程池
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3), //候客区,即阻塞队列
Executors.defaultThreadFactory(), //默认线程工厂
//new ThreadPoolExecutor.AbortPolicy()); //默认拒绝策略 线程满了,阻塞队列满了,做不处理处理方式,并且抛出异常
//new ThreadPoolExecutor.CallerRunsPolicy()); //哪里来的去哪里 main ok
//new ThreadPoolExecutor.DiscardOldestPolicy()); //队列满了会尝试去和第一个使用线程的竞争,如果竞争不过则会丢掉任务
new ThreadPoolExecutor.DiscardPolicy()); //队列满了不会抛出异常,会丢掉任务
try {
//最大承载=阻塞队列大小+最大线程池数目
//超出最大承载会抛出异常
for (int i = 0; i < 9; i++) {
// new Thread().start(); 传统方式
//使用线程池创建
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//程序结束需要关闭线程池
threadPool.shutdown();
}
}
}