Loading

并发编程-15 ThreadPoolExecutor线程池

线程池ExecutorService

image-20210728141340541

线程池状态

ThreadPoolExecutor使用int的高3位来表示线程池状态,低29位表示线程数量

状态 value 说明
RUNNING(当线程池创建出来的初始状态) 111 能接受任务,能执行阻塞任务
SHUTDOWN(调用shutdown方法) 000 不接受新任务,能执行阻塞任务 肯定可以 執行正在執行的任務
STOP(调用shutDownNow) 001 不接受新任务,打断正在执行的任务,丢弃阻塞任务
TIDYING(中间状态) 010 任务全部执行完,活动线程也没了
TERMINATED(终结状态) 011 线程池终结

构造方法(参数最多)

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue<Runnable> workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

1、核心线程数

2、最大线程数(应急线程数||空闲线程)

3、针对空闲线程的存活时间 如果超时了则把空闲的线程kill

4、针对3的时间单位

5、任务存放的队列

6、线程工厂,主要是产生线程---作用主要是给线程起个自定义名字

7、拒绝策略

工作方式

线程池中刚开始没有线程,当一个任务提交给线程池后,线程池会创建一个新线程来执行任务

当线程数达到 核心线程数上限,这时再加入任务,新加的任务就会被加入队列当中去

前提是有界队列,任务超过了队列大小时,会创建maximumPoolSize - corePoolSize数目的线程数目作为空显线程来执行任务

如果线程达到maximumPoolSize 仍然有新任务这时会执行拒绝策略

工厂方法

newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactorythreadFactory) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                            0L, TimeUnit.MILLISECONDS,
                            new LinkedBlockingQueue<Runnable>(),
                            threadFactory);
}


ExecutorService executorService = Executors.newFixedThreadPool(n);

核心线程数==最大线程数(没有救急线程被创建),因此也无需超时时间

阻塞队列是无界的,可以放任意数量的任务

使用于任务量已知,相对耗时的任务

newCachedThreadPool

public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                60L, TimeUnit.SECONDS,
                                new SynchronousQueue<Runnable>());
}


ExecutorService executorService = Executors.newCachedThreadPool()

核心线程数是0,最大线程数是Integer.MAX_VALUE,全部都是空闲线程,60s后回收

一个可根据需要创建新线程的线程池,如果现有线程没有可用的,则创建一个新线程并添加到池中,如果有被使用完但是还没销毁的线程,就复用该线程。终止并从缓存中移除那些已有60秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。

这种线程池比较灵活,对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。

newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1,0L, TimeUnit.MILLISECONDS,
                            new LinkedBlockingQueue<Runnable>()));
}

ExecutorService executorService = Executors.newSingleThreadExecutor();

希望多个任务排队执行,线程数固定为1,任务书多于1时,会放入无界队列排队,任务执行完毕后,这唯一的线程也不会被释放。

区别于自己创建一个单线程串行执行任务,如果任务执行失败而终止那么没有任何补救措施,而线程池还会创建一个线程,保证池的正常任务。

Executors.newSingleThreadExecutor()线程个数始终为1,且不能修改,

Executors.newFixedThreadPool(1) 初始时为1,以后还可以修改,对外暴露的是ThreadPoolExecutor对象,可以强转后调用setCorePoolSize等方法进行修改;

提交任务

提交一个任务

void execute(Runnable command);

提交一个任务 <有返回值>

Future<?> submit(Runnable task);

提交所有的任务

List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException;

提交 tasks 中所有任务,哪个任务先成功执行完毕,返回此任务执行结果,其它任务取消

T invokeAny(Collection<? extends Callable<T>> tasks) throws
InterruptedException, ExecutionException;

shutdown相关

线程池状态变为SHUTDOWN
不会接收新任务
但已提交任务会执行完
不会阻塞调用线程的执行

void shutdown();

线程池状态变为 STOP
不会接收新任务
会将队列中的任务返回
并用 interrupt 的方式中断正在执行的任务

List<Runnable> shutdownNow();

调用 shutdown后,调用线程并不会等待所有任务运行结束,可以利用此方法等待

boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
posted @ 2021-07-28 22:34  yescctv6  阅读(65)  评论(0编辑  收藏  举报