import java.util.concurrent.*;
/**
* 线程池的执行流程:
* 1.一个新的任务需要执行,判断核心线程是否已满,未满直接由核心线程执行
* 2.如果核心线程已满,判断队列是否已满,未满,则放入队列中等待前面的任务执行完
* 3.队列已满,就在最大线程池的允许范围内重开临时线程执行
* 4.如果最大线程都已经达到了,那就直接走解决策略
*/
public class ExecutorsDemo {
public static void main(String[] args) {
sevenParam();
// threeMethod
}
// Executors工具类的三大方法
// 三大方法其本质都是调用的ThreadPoolExecutor
// ThreadPoolExecutor(int corePoolSize,// 核心线程池大小,可以看成正常情况下可使用的线程数
// int maximumPoolSize,// 最大核心线程池大小,当核心线程数都不够时,允许运行的最大线程数,可以看成核心线程数加备用线程数的总和
// long keepAliveTime, //超时计数,当线程空闲时间达到keepAliveTime,该线程会退出,直到线程数量等于corePoolSize
// TimeUnit unit,//超时的单位,时分秒这种时间单位
// BlockingQueue<Runnable> workQueue,// 阻塞队列,当最大线程数都启动了,还有资源需要线程,就会进入阻塞队列等待
// ThreadFactory threadFactory,// 线程工厂,创建线程用的,一般不用动
// RejectedExecutionHandler handler// 解决策略,当线程池满了且阻塞队列也满了的时候,还有资源需要线程,这个时候的解决策略
// )
// 解决策略:当线程池满了,队列也满了时
// new ThreadPoolExecutor.AbortPolicy() // 抛出异常,java.util.concurrent.RejectedExecutionException
// new ThreadPoolExecutor.DiscardPolicy() // 满了不会抛出异常,但是会丢掉任务
// new ThreadPoolExecutor.DiscardOldestPolicy() // 满了不会抛出异常,会尝试去获取最早的线程,如果线程没有在用了,就可以获取到,如果没有获取到还是会扔掉任务
// new ThreadPoolExecutor.CallerRunsPolicy() // 哪来的去哪里执行,这里的话就是main线程执行
public static void threeMethod() {
// 介绍一下三大方法
// 创建一个单个线程
ExecutorService executorService = Executors.newSingleThreadExecutor();
// 创建一个固定大小的线程池,线程池里的线程数为10
// ExecutorService executorService = Executors.newFixedThreadPool(10);
// 缓存线程池,可变大小的线程池
// ExecutorService executorService = Executors.newCachedThreadPool();
try {
for (int i = 0; i < 10; i++) {
// 这里用的Executors.newSingleThreadExecutor(),所以就只是个单线程
// 有兴趣的可以一个一个的去试试,看看结果是怎么样的
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName());
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
// 线程池用完要关闭
executorService.shutdown();
}
}
// 建议使用这种手动创建线程池的方式,因为三大方法定义的线程池的最大核心线程数都非常大,电脑不可能带起这么多线程,绝对会爆炸
public static void sevenParam() {
// 调休方式
// 获取cpu的核数
// System.out.println(Runtime.getRuntime().availableProcessors());
// 怎么样设置最合适的核心线程数
// 1.cpu密集型,几核就是几,可以保持cpu效率最高
// ExecutorService executorService = new ThreadPoolExecutor(2, Runtime.getRuntime().availableProcessors(), 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
// 2.io密集型,判断你的程序中十分消耗io的线程,核心线程数大于它就行
// 下面是个普通例子
ExecutorService executorService = new ThreadPoolExecutor(2, 5, 2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
try {
// 这里故意让线程数超过最大能容忍的线程数,看看解决策略是怎么处理的
// 这里的解决策略是new ThreadPoolExecutor.AbortPolicy(),所以会抛出java.util.concurrent.RejectedExecutionException的错误
// 有兴趣的可以自己去试试每一种解决策略,看看结果
for (int i = 0; i < 9; i++) {
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName() + " ok");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}
Java线程池
于 2022-05-26 19:08:20 首次发布