线程池
- 为了节省资源, 可以复用已经创建的线程
线程池核心原理
- 创建线程池, 线程池为空
- 提交任务时, 池子会创建新的线程对象, 任务执行完毕, 线程会还给池子, 下次再提交任务时, 就不需要新创建线程了, 直接复用已有的线程
- 如果提交任务时, 池子没有空闲的线程, 也无法创建新的线程, 任务就会等待
线程池代码实现
-
创建线程池
创建线程池.png
//1. 创建线程池对象
ExecutorService pool = Executors.newCachedThreadPool();//第一种创建方式
ExecutorService pool1 = Executors.newFixedThreadPool(3);//第二种创建方式, 该线程池中最多只会创建3个线程
- 提交任务
利用submit方法
//2. 提交任务
//会创建5个线程来完成MyRunnable中的任务
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
pool.submit(new MyRunnable());
//2. 提交任务
//当sleep方法让线程休眠1秒钟再执行新任务时, 由于线程池中的已有线程有空来执行新任务了, 就会复用已有线程
pool.submit(new MyRunnable());
Thread.sleep(1000L);
pool.submit(new MyRunnable());
Thread.sleep(1000L);
pool.submit(new MyRunnable());
Thread.sleep(1000L);
pool.submit(new MyRunnable());
Thread.sleep(1000L);
pool.submit(new MyRunnable());
- 销毁线程池(实际上一般不销毁, 因为服务器一般都是24小时运行的)
//3. 销毁线程池
pool.shutdown();
自定义线程池
- 不断给自定义线程池提交任务时, 会有三个临界点:
- 当核心线程任务满了时, 会让任务排队
- 当排队任务队列满了时, 会创建临时线程
- 当核心线程满, 队列满, 临时线程满时, 对后面的任务会采用任务拒绝策略

自定义线程池的七个参数
//创建自定义线程池
ThreadPoolExecutor pool = new ThreadPoolExecutor(
3,//核心线程数量
6,//最大线程数, 最大线程数 >= 核心线程数
60,//临时线程空闲多久会被销毁, 值
TimeUnit.SECONDS,//空闲的单位
new ArrayBlockingQueue<>(3),//任务队列
Executors.defaultThreadFactory(),//如何创建线程
new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略
);
线程池拒绝服务的解决方案

解决方案
最大并行数
- 最大并行数即为CPU最多能并行处理多少任务, 例如4核8线程最大为8, 6核12线程最大为16
Java中获取CPU最大并行数
int count = Runtime.getRuntime().availableProcessors();
System.out.println(count);
线程池要多大才合适

如果项目中计算较多, 读取本地文件或读取数据库的操作较少, 则为CPU密集型运算
IO密集型运算则相反
