概述
- 使用线程池技术可以降低资源的消耗,提高响应速度和线程的可重复利用性
- 当提交一个新任务到线程池后,线程池首先会判断核心线程池(corePoolSize)里的线程是否都在执行任务,如果不是则创建一个新的工作线程来执行任务。如果核心线程池corePoolSize的线程都被占用在执行任务,线程判断工作队列是否已满,如果工作队列没有满:则将新提交的任务存储到工作队列中,如果工作队列已满:判断线程池(maximumPoolSize)的线程是否处于工作状态,如果没有,则创建一个新的工作线程来执行任务。如果线程池已满,则交给饱和策略处理这个任务。
线程池的五种状态
- RUNNING(运行中):线程池的初始化状态。线程池处在RUNNING状态时,能够接受新任务,以及对已添加的任务进行处理。
- SHUTDOWN(关掉):调用线程池的shutdown()接口时,线程池由RUNNING>>SHUTDOWN。处在SHUTDOWN状态时,不接搜新任务,但是能处理已添加的任务。
- STOP(停止):调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN)>> STOP。处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务。
- TIDYING(整理):当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由SHUTDOWN >> TIDYING。当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP >> TIDYING。
- TERMINATED(终止):线程池彻底终止,就变成TERMINATED状态。线程池处在TIDYING状态时,执行完terminated()之后,就会由TIDYING >> TERMINATED。
线程池的参数
- corePoolSize: 初始化指定的核心线程数量
- maximumPoolSize:允许的最大线程数。当前的线程数小于maximumPoolSize,则会新建线程来执行任务
- keepAliveTime:线程空闲的时间
- unit:keepAliveTime的单位
- workQueue:保存等待执行的任务的阻塞队列。初始化核心线程池已满时,队列未满会吧任务存储到队列中。
可供选择的几种阻塞队列
- ArrayBlockingQueue:是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。
- LinkedBlockingQueue:一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。
- SynchronousQueue:一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。
- PriorityBlockingQueue:一个具有优先级得无限阻塞队列
- PriorityBlockingQueue:一个具有优先级得无限阻塞队列
- threadFactory:用于设置创建线程的工厂。不指定 则是默认
- handler:线程池的拒绝策略。线程池中的线程已经饱和了,而且阻塞队列也已经满了,则线程池会选择一种拒绝策略来处理该任务
线程池提供的四种拒绝策略,也可以实现自己的拒绝策略:
- AbortPolicy:默认策略 抛出异常
- CallerRunsPolicy:由当前调用者所在的线程来执行任务
- DiscardOldestPolicy:丢弃阻塞队列中靠最前的任务,并执行当前任务
- DiscardPolicy:直接丢弃多余的任务
ThreadPoolExecutor executor=new
ThreadPoolExecutor(1,1,
10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(1),new ThreadPoolExecutor.CallerRunsPolicy());
for (int i = 0; i <5 ; i++) {
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
executor.shutdown();
}
常用方法
- getCorePoolSize() 返回核心线程数。
- getMaximumPoolSize() 返回允许的最大线程数。
- getPoolSize() 返回池中的当前线程数。
- getQueue() 返回此执行程序使用的任务队列。
- isShutdown() 如果此执行程序已关闭,则返回 true。
- isTerminated() 如果关闭后所有任务都已完成,则返回 true。
- execute(Runnable command) 在将来某个时间执行给定任务
- shutdown() 按过去执行已提交任务的顺序发起一个有序的关闭,但是不接受新任务。
- shutdownNow() 尝试停止所有的活动执行任务、暂停等待任务的处理,并返回等待执行的任务列表。
自定义线程名称
public class ThreadPoolExecutorTest {
// 命名线程工厂
static class NamedThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
NamedThreadFactory(String name) {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
if (null == name || name.isEmpty()) {
name = "pool";
}
namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
public static void main(String[] args) {
ThreadPoolExecutor executor=new
ThreadPoolExecutor(1,1,
10,TimeUnit.SECONDS,new ArrayBlockingQueue<>(1),new NamedThreadFactory("test-poll"),new ThreadPoolExecutor.CallerRunsPolicy());
for (int i = 0; i <5 ; i++) {
executor.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
}
executor.shutdown();
}
}
原文:https://blog.youkuaiyun.com/u010391342/article/details/88927281