池化技术
首先我们要了解的一个东西就是程序运行的本质是占用系统资源!
所以我们为了提高程序的使用效率,降低我们的一个性能消耗,就要把一些频繁创建的资源提前给准备好,这就是池化技术.
常见的有线程池,连接池,内存池,对象池…
其次我们为什么要用线程池-- 多路复用
关于线程池,我们只要掌握三大方法,七大参数,四种拒绝策略即可!下
三大方法
newFixedThreadPool(),newCachedThreadPool(),newSingleThreadExecutor()
public class Test1 {
public static void main(String[] args) {
//线程池 Executors原生三大方法
//固定大小
ExecutorService threadpool1= Executors.newFixedThreadPool(5);
//弹性收缩
ExecutorService threadpool2=Executors.newCachedThreadPool();
//只有一个
ExecutorService threadpool3=Executors.newSingleThreadExecutor();
try {
for (int i = 1; i <= 10; i++) {
//线程池,执行线程
threadpool3.execute(()->{
System.out.println(Thread.currentThread().getName()+"running...");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//线程池关闭
threadpool3.shutdown();
}
}
}
这里值得注意的是,我们创建线程池一般不会使用Excutors去创建,原因阿里巴巴开发手册上也有给出说明:
七大参数
我们先通过源码看下
new ThreadPoolExecutor(0, Integer.MAX_VALUE, // 约等于21亿
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<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;
}
下面我们就银行为例,具体的去讲解这七大参数:
** int corePoolSize**:核心池大小,对应的就是上图中的绿色的①②两个窗口,这两个窗口不管是高峰期还是平时都会开,平常如果①②窗口有人办理,其它来的人都会进入候客区等待,并不会开③④⑤窗口,也就是它的一个核心处理能力是同时只能有两个线程处理任务.
int maximumPoolSize:最大线程数,对应的就是图中红色的③④⑤窗口,这个平时是不开的,只有在高峰期才开的,也就是最大的处理能力就是同时有5个线程处理任务
long keepAliveTime:超时等待时间,也就是高峰期过后,超过多少时间还没有人来的话,③④⑤窗口就会关闭只保留核心的线程.
TimeUnit unit:时间单位,即超时等待的时间是以什么为单位.
BlockingQueue workQueue:阻塞队列,相当于我们的候客区,当柜台上有人办理业务的时候,我们就在候客区等待.
ThreadFactory threadFactory:创建线程的工厂
RejectedExecutionHandler handler:拒绝策略,即当银行的的所有窗口都有人在办理业务,并且候客区也满了的时候,这时如果再有人过来办理业务我们该采取何种方式拒绝.
public class Test2 {
public static void main(String[] args) {
ExecutorService threadPool=new ThreadPoolExecutor(
2,//核心线程数
5, //线程池最大大小
2L, //超时等待时间
TimeUnit.SECONDS,//时间单位
//阻塞队列
new LinkedBlockingDeque<>(3),
//不用变
Executors.defaultThreadFactory(),
//拒绝策略
new ThreadPoolExecutor.AbortPolicy()
);
try {
for (int i = 1; i <= 10; i++) {
//默认在处理
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+"running");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
四大策略
- 1、ThreadPoolExecutor.AbortPolicy(); 抛出异常,丢弃任务
- 2、ThreadPoolExecutor.DiscardPolicy();不抛出异常,丢弃任务
- 3、ThreadPoolExecutor.DiscardOldestPolicy(); 尝试获取任务,不一定执行!
- 4、ThreadPoolExecutor.CallerRunsPolicy(); 哪来的去哪里找对应的线程执行!也就是如果你是公司来的,人满了你就会公司去.
为什么会有这四种策略,其实对应的是上篇文章讲的阻塞队列的四组API
注意点:最大参数该如何设置?
CPU 密集型: 通过CPU设置
IO 密集型: 磁盘读写、 一个线程在IO操作的时候、另外一个线程在CPU中跑,造成CPU空闲。最大线程数应该设置为 IO任务数! 大文件读写耗时!单独的线程让他慢慢跑。
通过代码层面去设置
public class Test2 {
public static void main(String[] args) {
// 代码级别的
System.out.println(Runtime.getRuntime().availableProcessors());
ExecutorService threadPool = new ThreadPoolExecutor(
2,
Runtime.getRuntime().availableProcessors(), // 线程池最大大小5
2L,
TimeUnit.SECONDS,
new LinkedBlockingDeque<>(3), // 根据业务设置队列大小,队列大小一定要设置
Executors.defaultThreadFactory(), // 不用变
new ThreadPoolExecutor.CallerRunsPolicy() //拒绝策略
);
try {
// 队列 RejectedExecutionException 拒绝策略
for (int i = 1; i <= 10; i++) {
// 默认在处理
threadPool.execute(()->{
System.out.println(Thread.currentThread().getName()+" running....");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
threadPool.shutdown();
}
}
}
来源:CSDN
作者:你的眼睛会下雨
链接:https://blog.csdn.net/Hi_alan/article/details/104715382