线程池7大参数
- corePoolSize
- maximumPoolSize
- keepAliveTime
- unit
- workQueue
- threadFactory
- handler
corePoolSize:核心线程数。也可以设置超时,allowCoreThreadTimeOut参数来控制,可以使用allowCoreThreadTimeOut(true)方法设置
maximumPoolSize:最大线程数,包含核心线程数。
keepAliveTime: 除了核心线程数的超时时间(如果allowCoreThreadTimeOut为false)。
unit:超时时间的单位。
workQueue:阻塞队列。
threadFactory:线程工厂。
handler:拒绝策略。
线程执行流程
- 首先判断有没有线程,没有线程先创建线程,数量直到核心线程数。
- 如果已经达到核心线程数,进入阻塞队列。
- 如果阻塞队列达到最大数量,则创建新的线程,直到线程池达到最大线程数。
- 如果超了最大线程数,则执行拒绝策略。
- 当线程(非核心)的闲置时间超过了超时时间,则被回收,如果核心线程也设置了超时,也会被回收。
阻塞队列
种类
- LinkedBlockingQueue: 基于链表实现,默认长度为Integer.MAX_VALUE
。如果设置了这个参数,maximumPoolSize这个参数就没什么意义了。 - ArrayBlockingQueue:基于数组实现,长度可以自定义。
- PriorityBlockingQueue:优先级的阻塞队列,可以通过自定义比较器来控制优先级,这里只是弹出任务的优先级,具体能不能先执行,还得看cpu。
- DelayQueue:延迟队列,可以通过getDelay设置延迟时间。
- SynchronousQueue: 同步阻塞队列。
实例
PriorityBlockingQueue(线程池放一个 可以看出优先级)
public class ThreadTestUtil {
public static void main(String[] args) {
BlockingQueue blockingQueue = new PriorityBlockingQueue<TestTask>(5,(o1,o2)->{
return o1.getPriority()-o2.getPriority();
});
NamedThreadFactory namedThreadFactory = new NamedThreadFactory("xiaoyi-->",false);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1, 1, 3, TimeUnit.MINUTES, blockingQueue,
namedThreadFactory, new ThreadPoolExecutor.DiscardPolicy());
for (int i = 0; i < 10; i++) {
final int s = i;
threadPoolExecutor.execute(new TestTask(s));
}
}
}
@Data
class TestTask implements Comparable,Runnable{
private int priority;
TestTask(int priority){
this.priority = priority;
}
@Override
public int compareTo(@NotNull Object o) {
return priority;
}
@Override
public void run() {
System.out.println("shu-->"+priority);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
DelayQueue延迟队列
public class ThreadTestUtil {
public static void main(String[] args) {
DelayQueue delayQueue = new DelayQueue<DelayedElement>();
NamedThreadFactory namedThreadFactory = new NamedThreadFactory("xiaoyi-->",false);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 5, 3, TimeUnit.MINUTES, delayQueue,
namedThreadFactory, new ThreadPoolExecutor.DiscardPolicy());
for (int i = 0; i < 10; i++) {
final int s = i;
DelayedElement delayedElement = new DelayedElement(3000, s);
threadPoolExecutor.execute(delayedElement);
}
}
}
public class DelayedElement implements Delayed,Runnable {
/**
* 延迟时间
*/
private long delay;
/**
* 过期时间
*/
private long expire;
/**
* 优先级
*/
private int priority;
public DelayedElement(long delay, int priority) {
this.delay = delay;
this.priority = priority;
expire = System.currentTimeMillis() + delay;
}
/**
* 需要实现的接口,获得延迟时间 用过期时间-当前时间
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
/**
* 用于延迟队列内部比较排序
*/
@Override
public int compareTo(Delayed o) {
DelayedElement delayedElement = (DelayedElement) o;
return this.priority - ((DelayedElement) o).getPriority();
}
public int getPriority() {
return priority;
}
@Override
public void run() {
System.out.println("Kaishi--->"+priority);
}
}
SynchronousQueue同步阻塞队列
public class ThreadTestUtil {
public static void main(String[] args) {
SynchronousQueue syncQueue = new SynchronousQueue();
NamedThreadFactory namedThreadFactory = new NamedThreadFactory("xiaoyi-->",false);
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(0, 5, 3, TimeUnit.MINUTES, syncQueue,
namedThreadFactory, new ThreadPoolExecutor.DiscardPolicy());
threadPoolExecutor.execute(new PutTask(syncQueue));
threadPoolExecutor.execute(new TakeTask(syncQueue));
}
}
/**
* 放数据
*/
class PutTask implements Runnable {
BlockingQueue synchronousQueue;
PutTask(BlockingQueue synchronousQueue) {
this.synchronousQueue = synchronousQueue;
}
@Override
public void run() {
try {
for (int i = 0; i < 11; i++) {
System.out.println("放入的数字:"+i );
synchronousQueue.put(i);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 拿数据
*/
class TakeTask implements Runnable {
BlockingQueue synchronousQueue;
TakeTask(BlockingQueue synchronousQueue) {
this.synchronousQueue = synchronousQueue;
}
@Override
public void run() {
try {
while (true){
System.out.println(Thread.currentThread().getName() + " take " + synchronousQueue.take());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
四种常见的线程池
- newFixedThreadPool (固定线程池的线程数,队列是LinkedBlockingQueue)
- newCachedThreadPool (有超时时间,队列是SynchronousQueue)
- newSingleThreadExecutor (单线程的线程池,最大和核心线程数为1)
- newScheduledThreadPool (定时线程池,队列是DelayQueue)
拒绝策略
- ThreadPoolExecutor.AbortPolicy:抛出异常,丢弃任务,阻止系统正常工作。
- ThreadPoolExecutor.DiscardPolicy: 直接丢弃最新任务,但不抛出异常
- ThreadPoolExecutor.DiscardOldestPolicy: 丢弃最老的任务,然后重新尝试执行新任务
- ThreadPoolExecutor.CallerRunsPolicy: 只要线程池未关闭,直接调用线程池的线程执行该任务。
线程池的状态
- RUNNING: 运行的状态
- SHUTDOWN: 不接受新任务,但会继续处理队列的任务
- STOP: 不接受新任务,不会处理队列的任务,中断正在执行的任务
- TIDYING: 当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。
- TERMINATED: 线程池彻底终止