为什么要使用线程池?
避免因线程切换而造成的性能损耗
构造ThreadPoolExecutor线程池的参数
corePoolSize: 核心线程数
maximumPoolSize: 最大线程数
keepAliveTime: 线程空闲时间
unit: keepAliveTime参数单位
workQueue: 缓存线程任务阻塞队列
threadFactory: 指定创建线程的工厂
handler: 当提交任务数超过maximumPoolSize+workQueue之和时,任务会交给handler来处理,有4个取值:
1.new ThreadPoolExecutor.CallerRunsPolicy(): 拒绝任务的处理程序,它直接在execute方法的调用线程中运行拒绝任务
2.new ThreadPoolExecutor.AbortPolicy(): 抛出RejectedExecutionException拒绝任务的处理程序
3.new ThreadPoolExecutor.DiscardPolicy(): 拒绝任务的处理程序,静默丢弃被拒绝的任务
4.new ThreadPoolExecutor.DiscardOldestPolicy(): 拒绝任务的处理程序,丢弃最旧的未处理请求,然后重试execute
基本用法
1.定义Runnable或Callable类型的任务
2.创建ThreadPoolExecutor对象
3.将任务放入ThreadPoolExecutor对象中
4.任务运行结束后通过shutdown方法关闭ThreadPoolExecutor对象
代码展示
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
public class ThreadLocalTest extends Thread {
private final String name;
public ThreadLocalTest(String name) {
this.name = name;
}
@Override
public void run() {
System.out.println("Thread: " + name + "执行");
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread: " + name + "结束");
}
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 4, 200, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(10));
for (int i = 0; i < 10; i++) threadPoolExecutor.execute(new ThreadLocalTest(String.valueOf(i)));
threadPoolExecutor.shutdown();
}
}
打印展示
ThreadPoolExecutor线程池工作方式
1.创建线程池后,线程会随着任务到来的到来而创建
2.线程池中的任务数超出corePoolSize,workQueue队列未满,就会将任务放入到workQueue队列中
3.线程池中的任务数超出corePoolSize,workQueue队列已满,且线程池中的任务数小于maximumPoolSize,会创建maximumPoolSize减corePoolSize再减workQueue个新线程来处理被添加的任务
4.workQueue队列若无界,任务会一直丢到队列中,会导致OutOfMemoryError异常
代码展示
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
public class ThreadLocalTest implements Runnable {
@Override
public void run() {
}
public static void main(String[] args) {
/* 未超出核心线程数 */
extracted(4);
/* 超出核心线程数 */
extracted(8);
/* 超出缓存线程队列 */
extracted(12);
}
private static void extracted(int size) {
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 200,
TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(5));
for (int i = 0; i < size; i++) {
threadPoolExecutor.execute(new ThreadLocalTest());
System.out.println("线程池任务数量: " + threadPoolExecutor.getPoolSize() + " 队列任务数量: " +
threadPoolExecutor.getQueue().size() + " 已完成任务数量: " + threadPoolExecutor.getCompletedTaskCount());
}
System.out.println("-----分隔线-----");
threadPoolExecutor.shutdown();
}
}