线程池浅析
Posted java资料与技术共享平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线程池浅析相关的知识,希望对你有一定的参考价值。
导语
线程的创建、启动、销毁等是一个非常消耗资源的过程。引出线程池。
线程池作用
降低资源消耗,重复利用已创建好的线程。
提高响应速度,通过已经创建好的线程直接执行到达的任务,无需等待。
线程的统一管理,对线程统一分配、监控和调优(专人专职)。
线程池的创建
线程池的四种创建方式,本质都是通过改变构造函数的参数来创建不同的线程的。最终调用的构造函数都是:
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;
}
以下以demo分别说明线程池的创建:
一、创建缓存线程
ExecutorService threadPool = Executors.newCachedThreadPool(); for(int i=0;i<10;i++){ int temp = i;
threadPool.execute(new Runnable() { @Override
public void run() {
System.out.println(Thread.currentThread().getName()+","+temp);
}
});
}
threadPool.shutdown();// 停掉线程池
二、创建固定长度的线程(常用)
ExecutorService threadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { int temp = i;
threadPool.execute(new Runnable() { @Override
public void run() {
System.out.println(Thread.currentThread().getName()+","+temp);
}
});
}
threadPool.shutdown();// 停掉线程池
三、创建定时线程
ScheduledExecutorService threadPool = Executors.newScheduledThreadPool(3);
threadPool.schedule(new Runnable() { @Override
public void run() {
System.out.println("我是定时线程,三秒后启动");
}
},3, TimeUnit.SECONDS); // 第一个参数是任务,第二个参数是时间长度,第三个参数时间单位
threadPool.shutdown();// 停掉线程池
四、创建单线程
ExecutorService threadPool = Executors.newSingleThreadExecutor(); for (int i = 0; i < 10; i++) {
threadPool.execute(new Runnable() { @Override
public void run() {
System.out.println("我是单线程线程");
}
});
}
threadPool.shutdown();// 停掉线程池
线程池参数说明
重点:几乎是面试必问的。
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {}
corePoolSize:核心线程数
maximumPoolSize:最大线程数
keepAliveTimea:线程空闲时间
unit:TimeUnit枚举类型的值,代表keepAliveTime时间单位,可以取下列值:
TimeUnit.DAYS; //天
TimeUnit.HOURS; //小时
TimeUnit.MINUTES; //分钟
TimeUnit.SECONDS; //秒
TimeUnit.MILLISECONDS; //毫秒
TimeUnit.MICROSECONDS; //微妙
TimeUnit.NANOSECONDS; //纳秒
workQueue:阻塞队列,用来存储等待执行的任务,决定了线程池的排队策略,有以下取值:
ArrayBlockingQueue
LinkedBlockingQueue
SynchronousQueue
threadFactory:线程工厂,是用来创建线程的
handler:线程拒绝策略。当创建的线程超出maximumPoolSize,且缓冲队列已满时,新任务会拒绝,有以下取值:
ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务
线程的创建过程
下图是线程池的执行流程(图片摘自网络):
流程说明:
用户提交任务,先到核心线程池,判断核心线程池是都已满;
如何核心线程池未满,线程任务执行;如何核心线程已满,走下一步;
进入线程缓存队列,判断缓存队列是否已满;
如果线程缓存队列已满,进入最大线程池;
如果最大线程池未满,创建线程任务;
如果最大线程池已满,则拒绝。
后续
线程池核心参数的设置;
线程池的源码分析:
执行流程细化
缓存策略
拒绝策略
只有你学会把自己已有的成绩都归零,才能腾出空间去接纳更多的新东西,如此才能使自己不断的超越自己。
以上是关于线程池浅析的主要内容,如果未能解决你的问题,请参考以下文章
Java 线程池 ThreadPoolExecutor 八种拒绝策略浅析
newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段