1.什么是线程池
线程池其实就是一种多线程处理形式,处理过程中可以将任务添加到队列中,然后在创建线程后自动启动这些任务。
线程池最大的好处就是减少每次启动、销毁线程的损耗。
2.线程池参数介绍
参数名称 | 说明 |
corePoolSize | 正式员工的数量.(正式员工,一旦录用,永不辞退,干活的主力) |
maximumPoolSize | 正式员工+临时工的数目.(临时工:活多了,正式员工干不完,就招临时工干活,活不多的时候就裁掉) 也就是说核心线程不忙的时候,非核心线程就会被回收 |
keepAliveTime | 临时工允许的空闲时间 |
unit | keepaliveTime的时间单位,是秒,分钟,还是其他值. |
workQueue | 传递任务的阻塞队列 |
threadFactory | 创建线程的工厂,参与具体的创建线程工作.通过不同线程工厂创建出的线程相当于对⼀些属性进⾏了不同的初始化设置 |
RejectedExecutionHandler | 拒绝策略,如果任务量超出公司的负荷了接下来怎么处理. |
RejectedExecutionHandler
- AbortPolicy():超过负荷,直接抛出异常.(让程序员知道任务太多了,处理不过来,代码罢工)
- CallerRunsPolicy():调用者负责处理多出来的任务.(线程池满了,多出来的任务自己处理)
- DiscardOldestPolicy():丢弃队列中最老的任务.(这样新的任务可以排进队列里)
- DiscardPolicy():丢弃新来的任务,按照原有的节奏进行
3.使用Executors 创建常见的线程池
Executors创建线程池的几种方式:
- newFixedThreadPool:创建固定线程数的线程池
- newCachedThreadPool:创建线程数目动态增⻓的线程池.
- newSingleThreadExecutor:创建只包含单个线程的线程池.
- newScheduledThreadPool:设定延迟时间后执行命令,或者定期执行命令.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class Demo34 {public static void main(String[] args) {// 能够根据任务的数目, 自动进行线程扩容.
// Executors.newCachedThreadPool();
// 创建固定线程数目的线程池.
// Executors.newFixedThreadPool(10);
// 创建一个只包含单个线程的线程池.
// Executors.newSingleThreadExecutor();
// 创建一个固定线程个数, 但是任务延时执行的线程池.
// Executors.newScheduledThreadPool(10);// 创建固定线程数目的线程池.//ExecutorService service = Executors.newFixedThreadPool(10);// 能够根据任务的数目, 自动进行线程扩容.//ExecutorService service=Executors.newCachedThreadPool();//创建一个只包含单个线程的线程池.//ExecutorService service=Executors.newSingleThreadExecutor();//创建一个固定线程个数, 但是任务延时执行的线程池.ExecutorService service=Executors.newScheduledThreadPool(10);for (int i = 0; i < 1000; i++) {int id = i;service.submit(new Runnable() {@Overridepublic void run() {System.out.println("tjctsl" + id + ", " + Thread.currentThread().getName());}});}}
}
4.实现一个简单的线程池
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;class MyThreadPool {private BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(1000);private int maxPoolSize = 0;private List<Thread> threadList = new ArrayList<>();// 初始化线程池 (FixedThreadPool)public MyThreadPool(int corePoolSize, int maxPoolSize) {this.maxPoolSize = maxPoolSize;// 创建若干个线程for (int i = 0; i < corePoolSize; i++) {Thread t = new Thread(() -> {try {while (true) {Runnable runnable = queue.take();runnable.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();threadList.add(t);}}// 把任务添加到线程池中public void submit(Runnable runnable) throws InterruptedException {// 此处进行判定, 判定说当前任务队列的元素个数, 是否比较长.// 如果队列元素比较长, 说明已有的线程, 不太能处理过来了. 创建新的线程即可.// 如果队列不是很长, 没必要创建新的线程.queue.put(runnable);// 这里的 阈值 可以灵活调节if (queue.size() >= 500 && threadList.size() < maxPoolSize) {// 创建新的线程即可Thread t = new Thread(() -> {try {while (true) {Runnable task = queue.take();task.run();}} catch (InterruptedException e) {e.printStackTrace();}});t.start();}}
}public class Demo35 {public static void main(String[] args) throws InterruptedException {MyThreadPool threadPool = new MyThreadPool(10, 20);for (int i = 0; i < 10000; i++) {int id = i;threadPool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello " + id + ", " + Thread.currentThread().getName());}});}}
}