1.池化技术
程序的运行,本质:占用系统的资源! (优化资源的使用 => 池化技术)
线程池、连接池、内存池、对象池///… 创建、销毁。十分浪费资源
池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我。
2.线程池的好处
1、降低系统资源的消耗
2、提高响应的速度
3、方便管理
线程复用、可以控制最大并发数、管理线程
3.线程池的三大方法
先来看看阿里的开发手册是怎么说使用线程池的
吧!
简单代码实现:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @program: juc
* @description
* @author: 不会编程的派大星
* @create: 2021-04-26 16:34
**/
public class ThreeOfNew {
public static void main(String[] args) {
/**
* Executors,可以理解为一个工具类 ,创建线程池的三大方法
*/
//1.创建一个固定大小的线程池
ExecutorService threadPool = Executors.newFixedThreadPool(5);
//2.创建单个线程的线程池
//ExecutorService threadPool = Executors.newSingleThreadExecutor();
//3.创建一个可伸缩的线程池,大小不固定
//ExecutorService threadPool = Executors.newCachedThreadPool();
try {
for (int i = 1; i <= 10 ; i++) {
threadPool.execute(() -> {
System.out.println(Thread.currentThread().getName()+"is ok");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
//线程池用完后关闭
threadPool.shutdown();
}
}
}
执行结果:
*1.固定大小线程池
*2.单个线程的线程池
*3.课伸缩的线程池
4.线程池七大参数
这里我们源码来一层层分析,首先先来看看三大方法是怎么创建线程池的
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
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>());
}
可以看出,都是new了一个 ThreadPoolExcutor
我们再来看看ThreadPoolExcutor的创建
public ThreadPoolExecutor(int corePoolSize, // 核心线程池大小
int maximumPoolSize, // 最大核心线程池大小
long keepAliveTime, // 超时没有人调用就会释放
TimeUnit unit, // 超时单位
// 阻塞队列
BlockingQueue<Runnable> workQueue,
// 线程工厂:创建线程的,一般 不用动
ThreadFactory threadFactory,
// 拒绝策略
RejectedExecutionHandler handle ) {
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;
}
为什么阿里不推荐用excutors创建线程池呢?
这里我们用 在银行取钱的例子来说明一下这七大参数和ThreadPoolExcutorf的妙处吧
举例说明:
简单代码实现:
因为实际开发中工具类Executors 不安全,所以需要手动创建线程池,自定义7个参数。
这里先说明四种拒绝策略,通过例子说明
/**
* 四种拒绝策略:
*
* new ThreadPoolExecutor.AbortPolicy()
* 银行满了,还有人进来,不处理这个人的,抛出异常
*
* new ThreadPoolExecutor.CallerRunsPolicy()
* 哪来的去哪里!比如你爸爸 让你去通知妈妈洗衣服,妈妈拒绝,让你回去通知爸爸洗
*
* new ThreadPoolExecutor.DiscardPolicy()
* 队列满了,丢掉任务,不会抛出异常!
*
* new ThreadPoolExecutor.DiscardOldestPolicy()
* 队列满了,尝试去和最早的竞争,也不会抛出异常!
*/
主要代码:
import java.util.concurrent.*;
/**
* @program: juc
* @description
* @author: 不会编程的派大星
* @create: 2021-04-26 17:07
**/
public class Seven {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
//核心线程池大小,(默认开启的窗口)
2,
//最大核心线程池大小(总共5个窗口)
5,
//超时3秒没有人调用就会释,关闭窗口
3,
// TimeUnit unit, 超时单位 秒
TimeUnit.SECONDS,
// 阻塞队列(候客区最多3人)
new LinkedBlockingDeque<>(3),
// 默认线程工厂
Executors.defaultThreadFactory(),
// 4种拒绝策略之一:
// 队列满了,尝试去和 最早的竞争,也不会抛出异常!
new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
for (int i = 1; i <=10 ; i++) {
threadPoolExecutor.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 窗口可以取钱");
});
}
}catch (Exception e){
e.printStackTrace();
}finally {
threadPoolExecutor.shutdown();
}
}
}
执行结果:
5.四种拒绝策略
a:
- new ThreadPoolExecutor.AbortPolicy()
- 银行满了,还有人进来,不处理这个人的,抛出异常
b:
- new ThreadPoolExecutor.CallerRunsPolicy()
- 哪来的去哪里!比如你爸爸 让你去通知妈妈洗衣服,妈妈拒绝,让你回去通知爸爸洗
c:
- new ThreadPoolExecutor.DiscardPolicy()
- 队列满了,丢掉任务,不会抛出异常!
d:
- new ThreadPoolExecutor.DiscardOldestPolicy()
- 队列满了,尝试去和最早的竞争,也不会抛出异常!
/***