线程池:三大方法,七大参数,四种拒绝策略
线程池,首先最要记住上面的话
池化技术
程序的运行,本质占用系统的资源!优化资源的使用!–>池化技术
线程池,连接池,内存池,对象池…
池化技术:事先准备好一些资源,有人要用就来我这拿,用完之后还给我.
线程池的好处:
1.降低资源的消耗
2.提高响应的速度
3.方便管理
总结:线程复用,控制最大并发数,管理线程
//最简单的线程池创建线程
ExecutorService threadpool = Executors.newSingleThreadExecutor();//单个线程
for (int i = 0; i < 10; i++) {
threadpool.execute(()->{
});
}
package com.qiu.pool;
//Executors工具类3大方法
//使用了线程池之后,就要用线程池来创建线程
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo01 {
public static void main(String[] args) {
//ExecutorService threadpool = Executors.newSingleThreadExecutor();//单个线程
//ExecutorService threadpool = Executors.newFixedThreadPool(100);//创建一个固定的线程池的大小
ExecutorService threadpool = Executors.newCachedThreadPool();//可伸缩的,遇强则强,遇弱则弱
try {
for (int i = 0; i < 100; i++) {
threadpool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}}catch (Exception e){
e.printStackTrace();
}finally {
//线程用完,程序结束,关闭线程池
threadpool.shutdown();
}
}
}
三大方法:
ExecutorService threadpool = Executors.newSingleThreadExecutor();//单个线程
ExecutorService threadpool = Executors.newFixedThreadPool(100);//创建一个固定的线程池的大小
ExecutorService threadpool = Executors.newCachedThreadPool();//可伸缩的,遇强则强,遇弱则弱
七大参数
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
newFixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
newCachedThreadPool
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,//约等于21亿
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
本质:开启线程,调用了是ThreadPoolExecutor
根据阿里开发手册:
终极源码:
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;
}
long keepAliveTime,//超时没有线程进来执行的话,就会关掉这个核心线程
下面举一个具体的实例来加深理解
银行办理业务:先进来的人在窗口办理业务(对应先来的线程进入线程池)
开放的柜台满人之后,接下来近来的人就会在候客区就坐.(对应核心线程池全部占用后,会去阻塞队列)
如果此时还有人进来办理业务就会开放更多的窗口(对应还有更多的线程进来的话,就会扩大最大核心线程数.),
如果说这个时候所有窗口都满了的话,就只能通知后来的客户去别的地方了(对应线程池会使用拒绝策略去阻止线程进来)
四种拒绝策略
new ThreadPoolExecutor.AbortPolicy());//银行满了,还有人进来,不处理这个人了,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy());//哪来的,去哪里!(main线程来的,就会去main线程执行)都会执行到,不会抛出异常.
new ThreadPoolExecutor.DiscardPolicy());//队列满了不会抛出异常,但是会丢掉任务.
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常
package com.qiu.pool;
//Executors工具类3大方法
//使用了线程池之后,就要用线程池来创建线程
import java.util.concurrent.*;
/**
* new ThreadPoolExecutor.AbortPolicy());//银行满了,还有人进来,不处理这个人了,抛出异常
*new ThreadPoolExecutor.CallerRunsPolicy());//哪来的,去哪里!(main线程来的,就会去main线程执行)都会执行到,不会抛出异常.
*new ThreadPoolExecutor.DiscardPolicy());//队列满了不会抛出异常,但是会丢掉任务.
* new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常
*
*/
public class Demo02 {
public static void main(String[] args) {
ExecutorService threadpool = new ThreadPoolExecutor(2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),Executors.defaultThreadFactory(),
//new ThreadPoolExecutor.AbortPolicy());//银行满了,还有人进来,不处理这个人了,抛出异常
//new ThreadPoolExecutor.CallerRunsPolicy());//哪来的,去哪里!(main线程来的,就会去main线程执行)都会执行到,不会抛出异常.
//new ThreadPoolExecutor.DiscardPolicy());//队列满了不会抛出异常,但是会丢掉任务.
new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试去和最早的竞争,也不会抛出异常
try {
//最大承载的是队列加最大核心线程:3+5 = 8
for (int i = 1; i < 100; i++) {
threadpool.execute(()->{
System.out.println(Thread.currentThread().getName()+"ok");
});
}}catch (Exception e){
e.printStackTrace();
}finally {
//线程用完,程序结束,关闭线程池
threadpool.shutdown();
}
}
}
由于这个拒绝策略是默认的,所以可以在自定义的时候,可以写,也可以不写,不写那就是默认:
1.CPU密集型 看电脑核心.几个核心就是几条线程可以同时执行.保证CPU效率最高
Runtime.getRuntime().availableProcessors()
2.IO密集型:判断你的程序中十分耗IO的线程数为多少,一般设置两倍
一个程序,15个大型任务,io十分占用资源!
笔记自己看视频做的,视频链接如下:
B站地址:https://space.bilibili.com/95256449