线程池
Executors
通过Executtors的静态工厂方法可以创建三个线程池的包装对象:
- ForkJoinPool
- ThreadPoolExecutor
- ScheduledThreadPoolExecutor
Executtors的五个核心方法:
// 返回ForkJoinPool对象,把CPU数量设置为默认的并行度 Runtime.getRuntime().availableProcessors()
Executor pool1 = Executors.newWorkStealingPool();
// 创建一个可伸缩的线程池,如果任务增加,再次创建新线程处理任务,最大为Integer.MAX_VALUE,容易抛出OOM
Executor pool2 = Executors.newCachedThreadPool();
// 返回的是ScheduledExecutorService,与newCachedThreadPool差不多,区别是newScheduledThreadPool不回收工作线程,存在OOM风险
Executor pool3 = Executors.newScheduledThreadPool(3);
// 创建一个单线程的线程池,相当于单线程执行任务,保证按任务的提交顺序执行
Executor pool4 = Executors.newSingleThreadExecutor();
// 创建一个固定大小的线程池
Executor pool5 = Executors.newFixedThreadPool(3);
拒绝策略
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
自定义线程池
// 自定义线程池
Executor pool6 = new ThreadPoolExecutor(
3, // core
5, // max
5L, // 线程空闲时间
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5), // 阻塞队列
new UserThreadFactory("交易"),
new UserRejectHandler()
);
自定义工厂类
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class UserThreadFactory implements ThreadFactory {
private final String namePrefix;
private final AtomicInteger nextId = new AtomicInteger();
public UserThreadFactory(String group){
namePrefix = "中国杭州-"+group+"线程-编号-";
}
@Override
public Thread newThread(Runnable r) {
String name = namePrefix + nextId.getAndIncrement();
// Thread thread = new Thread(null, r, name, 0);
// jdk11
Thread thread = new Thread(null, r, name, 0,false);
System.out.println(name+"启动成功!");
return thread;
}
}
class Task implements Runnable{
@Override
public void run() {
System.out.println("hello world");
}
}
线程池的最大设置
计算密集型的任务,个有Ncpu个处理器的系统通常通过使用一个Ncpu + 1个线程的线程池来获得最优的利用率
IO 密集型
Nthreads = Ncpu x Ucpu x (1 + W/C),其中
Ncpu = CPU核心数
Ucpu = CPU使用率,0~1
W/C = 等待时间与计算时间的比率
线程池的5种状态
private static final int COUNT_BITS = 29;
// 得到左边三位 private static final int COUNT_MASK = (1 << COUNT_BITS) - 1
private static final int COUNT_MASK = 536870911;
// 此状态表示线程池还能接受新的任务 RUNNING = COUNT_BITS << -1
private static final int RUNNING = -536870912;
// 此状态表示不再接受新任务,但可以继续执行队列中的任务 SHUTDOWN = COUNT_BITS << 0
private static final int SHUTDOWN = 0;
// 此状态全面拒绝,并中断正在处理的任务 STOP = COUNT_BITS << 1
private static final int STOP = 536870912;
// 表示所有任务已经被终止 TIDYING = COUNT_BITS << 2
private static final int TIDYING = 1073741824;
// 表示已清理完现场 TIDYING = TERMINATED << 3
private static final int TERMINATED = 1610612736;