JAVA线程池常见用法及其原理
JAVA线程池常见用法:
1.代码实现
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author LiSanWei
*/
@Slf4j
public class GlobalThreadPool {
/**
* 自定义线程工作,便于排查线程问题
*/
public static class CustomDefinedThreadFactory implements ThreadFactory {
private final StringnamePrefix;
/* 1.线程数叠加*/
private final AtomicIntegernextId =new AtomicInteger(1);
/* 2.定义线程组名称,在 jStack 问题排查时,非常有帮助*/
CustomDefinedThreadFactory(String whatFeatureOfGroup) {
namePrefix ="From UserThreadFactory's " + whatFeatureOfGroup +"-Worker-";
}
@Override
public ThreadnewThread(Runnable task) {
String name =namePrefix +nextId.getAndIncrement();
Thread thread =new Thread(null, task, name, 0);
thread.setUncaughtExceptionHandler( (t,e) -> { System.out.println(t + "" + e); e.printStackTrace();});
log.info("====threadName:{}====", thread.getName());
return thread;
}
}
/**
* 自定义执行线程池
*/
public static final ThreadPoolExecutorTHREAD_POOL_EXECUTOR =new ThreadPoolExecutor(
/* 核心线程数*/
12,
/* 最大线程数*/
12,
/* 最大线程数释放等待时间*/
60,
/* 阻塞队列*/
TimeUnit.SECONDS, new ArrayBlockingQueue<>(2000)
/* 定义线程工厂*/
, new CustomDefinedThreadFactory("Manager-Pool-Name")
/* 线程拒绝策略 常见4种拒绝策略*/
, new ThreadPoolExecutor.AbortPolicy()
);
}
2.核心参数讲解
corePoolSize: 核心线程数即核心池的大小。 当线程提交任务后,就会创建一个线程去执行任务,当线程池中的线程数目达到corePoolSize后,随着提交任务越来越多,就会把待执行的任务放到缓存内存队列中去,如果当前线程池中的线程数目 小于corePoolSize ,则每来一个任务,就会创建一个线程去执行这个任务
maximumPoolSize: 线程池最大线程数,它表示在线程池中最多能创建多少个线程;如果当前线程池中的线程数目 大于corePoolSize,则每来一个任务,会尝试将其添加到内存队列中,若添加成功,则该任务会等待空闲线程将其取出去执行;若添加失败(一般来说是任务缓存队列已满),则会尝试创建新的线程去执行这个任务
keepAliveTime: 表示线程没有任务执行时最多保持多久时间会终止。
unit: 参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:
policy:线程拒绝策略
3.流程简述
1、判断线程池的核心线程是否都在执行任务,如果不是(核心线程空闲或者还有核心线程没有被创建)则创建一个新的工作线程来执行任务
2、线程池判断工作队列是否已满,如果工作队列没有满,则将新提交的任务存储在这个工作队列里。如果工作队列满了,则判断最大线程数
3、判断线程池核心线程数是否大于最大线程数,如果不大于,则创建线程进入等待队列。继续执行任务,如果已经阻塞队列也满了,则交给策略来处理这个任务
网友评论