池化技术:
池化技术 (Pool) 是一种很常见的编程技巧,在请求量大时能明显优化应用性能,降低系统频繁建连的资源开销。我们日常工作中常见的有数据库连接池、线程池、对象池等,它们的特点都是将 “昂贵的”、“费时的” 的资源维护在一个特定的 “池子” 中,规定其最小连接数、最大连接数、阻塞队列等配置,方便进行统一管理和复用,通常还会附带一些探活机制、强制回收、监控一类的配套功能。
线程池:
先启动若干数量的线程,并让这些线程都处于睡眠状态,当需要一个开辟一个线程去做具体的工作时,就会唤醒线程池中的某一个睡眠线程,让它去做具体工作,当工作完成后,线程又处于睡眠状态,而不是将线程销毁。
(三大方法,七大参数,四种拒绝策略)
好处:
1:降低资源消耗。-->线程复用
2:提高相应速度。-->可以控制最大并发数
3:方便管理。-->管理线程
三大方法:
public class demo01 {
public static void main(String[] args) {
//Executors工具类,三大方法
//ExecutorService service = Executors.newSingleThreadExecutor();//单个线程
//ExecutorService service=Executors.newFixedThreadPool(5);//创建一个固定的线程池
ExecutorService service=Executors.newCachedThreadPool();//可伸缩的线程池
try {
for (int i = 0; i < 10; i++) {
//使用线程池后,就用线程池来创建线程
service.execute(()->{
System.out.println(Thread.currentThread().getName()+" success");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池需要关闭
service.shutdown();
}
}
}
七大参数:
//Executors工具类
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,//21亿-->OOM溢出
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;
}
关于七大参数的理解:
以去银行办理业务为例:
阿里巴巴Java开发手册里的约束:
所以我们最好自己手动创建线程池。
手动创建线程池:
示例:
public class demo01 {
public static void main(String[] args) {
//自己创建线程池:
ExecutorService service=new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
try {
for (int i = 1; i <= 9; i++) {
//使用线程池后,就用线程池来创建线程
service.execute(()->{
System.out.println(Thread.currentThread().getName()+" success");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池需要关闭
service.shutdown();
}
}
}
四种拒绝策略:
1:AbortPolicy() 如果超出线程池最大大小+阻塞队列大小就抛出异常。
2:CallerRunsPolicy() 让超出的线程回溯。
3:DiscardPolicy() 如果超出线程池最大大小+阻塞队列大小不抛出异常。
4:DiscardOldestPolicy() 如果超出线程池最大大小+阻塞队列,尝试去和最早的线程竞争,也不会抛出异常。