线程是调度CPU资源的最小单位,线程模型分为KLT模型和ULT模型,Java采用的是KLT模型,java线程与OS(内核)线程保持1:1的映射关系,就是java创建一个线程,内核与之相对应的也会创建一个线程
image.png线程池的介绍
在并发请求数量多的情况下,而且每个线程的执行时间很短,毫秒级就会执行结束,这样就会频繁的创建和销毁线程,降低了效率,可能出现创建和销毁线程的时间要大于线程执行的时间,线程池的出现就是为了解决上述的问题.
使用场景(绝大多数的场景)
线程执行时间短
线程要处理的任务数多
线程池的优势
重用已有的线程,减少创建和销毁线程
提高相应速度,当任务到达时,不需等待直接使用已有的线程,反应快
提高线程的可管理性,线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行同意的分配,调优的监控.
Java 线程池的创建
Java 创建线程池非常重要的类ThreadPoolExecutor其中有4个构造函数,但是最终调用的是7个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
7个参数
int corePoolSize, 核心线程数
int maximumPoolSize, 最大线程数 = 非核心线程数 + 核心线程数
long keepAliveTime, 最大允许线程不干活的时间,超过时间则销毁线程,其实就是获取阻塞队列的等待时间,如果在这段时间队列中没有放入新的任务,那当先的线程就会终止,其实就是跳出了while循环, 后续会分析到
TimeUnit unit, keepAliveTime的时间单位
BlockingQueue<Runnable> workQueue, 存放任务数队列
ThreadFactory threadFactory, 线程创建工厂
RejectedExecutionHandler handler 拒绝策略
线程池的5中状态
ctl变量包含了两个信息,一个是运行状态,一个是线程池的线程数,整型共32位,其中高3位为运行状态,其余29位为线程数
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int RUNNING = -1 << COUNT_BITS;
private static final int SHUTDOWN = 0 << COUNT_BITS;
private static final int STOP = 1 << COUNT_BITS;
private static final int TIDYING = 2 << COUNT_BITS;
private static final int TERMINATED = 3 << COUNT_BITS;
private static int runStateOf(int c) { return c & ~CAPACITY; }//当前运行状态
private static int workerCountOf(int c) { return c & CAPACITY; }//当前线程数
private static int ctlOf(int rs, int wc) { return rs | wc; }//通过状态和线程生成ctl
下面的图片根据高3位可以得出
RUNNING 111
SHUTDOWN 000
STOP 001
TIDYING 010
TERMINATED 011
image.png
image.png
image.png
拒绝策略
new ThreadPoolExecutor.AbortPolicy ();//抛出异常
image.png
new ThreadPoolExecutor.DiscardPolicy (); //什么也没做
image.png
new ThreadPoolExecutor.DiscardOldestPolicy ();//将队列中队头的的任务poll出来,不做处理,就是丢弃掉了
image.png
new ThreadPoolExecutor.CallerRunsPolic();//当前提交任务的线程直接执行,不交给线程池来执行(比如tomcat的线程再执行线程池的execute方法,被拒绝,当使用此拒绝策略时,tomcat的线程直接执行任务)
image.png
image.png
看上图可知,如果使用CallerRunsPolic策略,那么main线程就执行了此任务
网友评论