线程池的使用
假定某业务需要需要线程池来置顶任务。
设置线程池基本参数如下,观察执行情况:
核心线程数:2;最大线程数5;队列长度为3.
class TaskProcess {
public void run() {
// 最大线程到底该如何定义
// 1、CPU 密集型,几核,就是几,可以保持CPu的效率最高!
// 2、IO 密集型 > 判断你程序中十分耗IO的线程,
// 假设 程序有15个大型任务 ,io十分占用资源,那就至少留15个max线程(一般来两倍)
// 获取CPU的核数
//System.out.println(Runtime.getRuntime().availableProcessors());
//手动创建线程成
ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
2,
5,
3,
TimeUnit.SECONDS,
new LinkedBlockingQueue<>(3),
Executors.defaultThreadFactory(),
//抛出RejectedExecutionException的被拒绝任务的处理程序。
new ThreadPoolExecutor.AbortPolicy()
//被拒绝任务的处理程序,直接在execute方法的调用线程中运行被拒绝的任务(main线程执行),除非执行程序已关闭,在这种情况下,任务将被丢弃。
//new ThreadPoolExecutor.CallerRunsPolicy()
//拒绝任务的处理程序,丢弃最旧的未处理请求,然后重试execute ,除非执行程序被关闭,在这种情况下任务被丢弃。
//new ThreadPoolExecutor.DiscardOldestPolicy()
//被拒绝任务的处理程序,它默默地丢弃被拒绝的任务。
//new ThreadPoolExecutor.DiscardOldestPolicy()
);
try {
for (int i = 0; i < 10; i++) {
int finalI = i;
poolExecutor.execute(() -> {
try {
//业务代码
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
printInfo(poolExecutor, finalI + "");
});
}
} catch (Exception e) {
e.printStackTrace();
} finally {
poolExecutor.shutdown();
}
}
public static void printInfo(ThreadPoolExecutor executor, String name) {
BlockingQueue<Runnable> queue = executor.getQueue();
System.out.println(Thread.currentThread().getName() + "--->" + name + "<----" +
" 核心数: " + executor.getCorePoolSize() +
" 活动线程数: " + executor.getActiveCount() +
" 最大线程数: " + executor.getMaximumPoolSize() +
" 任务完成数: " + executor.getCompletedTaskCount() +
" 队列大小: " + (queue.size() + queue.remainingCapacity()) +
" 当前排队线程数: " + queue.size() +
" 队列剩余大小: " + queue.remainingCapacity()
);
}
}
观察不同拒绝策略的执行效果:
new ThreadPoolExecutor.AbortPolicy():
抛出RejectedExecutionException的被拒绝任务的处理程序。{当达到线程池的最大处理能力的时候,直接抛异常,一些比较重要的业务可以采用该策略,当线程池达到最大负载的时候通过异常信息及时发现}
预期:线程池可以处理8个并发任务,提交10个任务会报异常。
本文来自博客园,作者:iyandongsheng,转载请注明原文链接:https://www.cnblogs.com/ieas/articles/16033568.html