线程池 ThreadPoolExecutor

线程池 ThreadPoolExecutor

ThreadPoolExecutor是线程池类的基本实现,其他线程池的扩展基本都是基础于改类,这个类是学好线程池的基础,下面来看下改类实现的接口。

1. Executor

线程池根接口,该接口只提供了一个方法

  1. void execute(Runnable command);
    提交要运行的任务
2. ExecutorService

执行服务类,该接口继承了Executor接口并提供了对线程池操作的扩展方法,如果shutdown()关闭线程池,shutdownNow()立即关闭线程池,submit(Callable task)提交带有返回值的任务等方法,具体如下。

  1. void shutdown();
    关闭线程池,这个关闭过程并不是立即关闭线程池,而是首先禁止在往线程池里提交任务,然后等待当前线程池中的任务运行完,然后才是真正的关闭线程池。

  2. List shutdownNow();
    立即关闭线程池,当调用该方法后会立即关闭线程池,并返回当前线程池中还未执行的任务(还在执行中的任务会等待其执行完)。

  3. boolean isShutdown();
    判断当前线程池是否处于已经关闭

  4. boolean isTerminated();
    判断线程池是否已经完全关闭,这个与isShutdown();有点区别,isShutdown()是表示用户调用了shutdownNow()或shutdownNow()方法,但是线程池并还未真正的完成关闭(必须得等已经执行的任务执行完),因为完成关闭线程还需要一定的时间,说以如果线程池处于关闭状态但还未完成关闭的这个过程,调用isShutdown()返回的true,而调用 isTerminated()返回的false。

  5. boolean awaitTermination(long timeout, TimeUnit unit)    throws InterruptedException;
    等待线程池关闭完成,这个方法会休眠当前线程,直到线程关闭完成或超时,才会重新唤醒调用该方法的线程。

  6. Future submit(Callable task);
    提交一个Callable任务到线程池中,Callable与Runnable的区别就是Callable是带有返回值的,而Runnable没有。

  7. Future submit(Runnable task, T result);
    提交一个Runnable任务到线程池中,并指定当该任务执行完后的返回值,这个方法在AbstractExecutorService类中的实现是创建一个FutureTask然后吧这个FutureTask放到线程任务中,并在其内部构造一个RunnableAdapter
    对象该对象的call()方法就是调用task.run(),返回值就是我们给定的返回值。

  8. Future<?> submit(Runnable task);
    提交一个任务到线程池中

  9. List<Future> invokeAll(Collection<? extends Callable> tasks) throws InterruptedException;
    这个方法提交的是一个任务集合到线程池中,这个方法在AbstractExecutorService类中的实现是,首先将集合中的Caooable任务封装成一个Future集合,然后在吧集合都添加到任务中,然后在遍历Future集合分别调用他们的f.get();方法,等调用完成后在会这个Future集合,这里之说以要调用f.get()方法的原因是,f.get()返回会等待当前Future对应的任务执行完才返返回,所有每个Future都调用他们的get()方法,那么返回的就是已经执行完成的Future集合。

  10. List<Future> invokeAll(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)    throws InterruptedException;
    这个方法与invokeAll(Collection<? extends Callable> tasks)方法类似,只不过添加了执行超时时间,但是需要注意的一点是,这里的超时并不会抛出异常,这个方法在AbstractExecutorService类中这个方法的实现逻辑是,

    1. 将Collable任务集合封装成Future集合futures.add(newTaskFor(t));
    2. 遍历futures集合,调用execute((Runnable)futures.get(i));将任务添加到线程池中,同时每将一个任务放入到线程中,都会判断是否超时,如果超时就返回,(如果超时时间设置的非常短,会出现任务还没有全部放入到线程池中)
    3. 循环遍历futures调用他们的get方法,这里每次调用都会判断是否已经超时,如果已经超时直接返回
  11. T invokeAny(Collection<? extends Callable> tasks) throws InterruptedException, ExecutionException;

  12. T invokeAny(Collection<? extends Callable> tasks, long timeout, TimeUnit unit)  throws InterruptedException, ExecutionException, TimeoutException;

3. AbstractExecutorService

抽象的线程池类,这个方法实现了ExecutorService方法,并实现了部分方法,如并提供了一些用于子类调用的方法,如

  1. Future<?> submit(Runnable task)
  2. Future submit(Runnable task, T result)
  3. Future submit(Callable task)
  4. T doInvokeAny(Collection<? extends Callable> tasks,
  5. boolean timed, long nanos),invokeAny(Collection<? extends Callable> tasks)

并提供了部用于子类调用的方法

  1. protected RunnableFuture newTaskFor(Runnable runnable, T value)
  2. protected RunnableFuture newTaskFor(Callable callable)
    这两个方法就是将Runnable或Callable任务封装成一个Future对象,因为在线程池中,真正让线程执行的是一个Future对象,而并非我们提交的任务,这是一种封装,即将Runnable或Callable接口都统一封装成RunnableFuture对象,方便后面管理。
4. ThreadPoolExecutor

ThreadPoolExecutor是线程池的基本实现类,该类定义了一个原子操作变量
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
这个变量是个Integer类型,该变量的高3位用来表示当前线程池的运行状态,低29位用来表示当前线程池中的任务树。总的来说就是用一个变量来记录当前线程池的运行状态和线程池的任务数。下面来看下,他是这么标识这些状态的
线程池状态变量

// COUNT_BITS = 29,Integer.SIZE  = 32
private static final int COUNT_BITS = Integer.SIZE - 3;
// 最大容量,即当前线程池能容纳的最大的任务数
// 00011111111111111111111111111111 (536870911)
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
// 00100000000000000000000000000000
// 线程池运行状态常量
// 运行状态,该状态下,线程池能够接受新任务,并且执运行队列中的任务 11100000000000000000000000000000
private static final int RUNNING    = -1 << COUNT_BITS;
// 关闭状态,该状态下,线程池不能在接受新的任务,定任然执行队列中的任务 00000000000000000000000000000000
private static final int SHUTDOWN   =  0 << COUNT_BITS;
//  停止状态,该状态下,线程池不能在接受新的任务,也执行队列中的任务,且要中断正在执行的任务 00100000000000000000000000000000
private static final int STOP       =  1 << COUNT_BITS;
// 整理状态,该状态下,线程池中所有任务均已终止,workCount = 0工作线程数为0,worker转到TIDYING状态的线程,准备执行terminated()方法 01000000000000000000000000000000
private static final int TIDYING    =  2 << COUNT_BITS;
// 终止状态,该状态下,线程池已完成关闭,即worker已经执行完terminated()方法,01100000000000000000000000000000
private static final int TERMINATED =  3 << COUNT_BITS;

线程池的主要实现类,该类是核心类,里面写了线程池的具体实现方法,具体的实现流程如下

  1. 定义线程任务的状态,在该类中定义任务运行的状态常量,很多都
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值