Executor 框架入门

学习Executor的过程中,遇到很多新的接口和类,先列举一下;

Executor    , Executors  ,ExecutorService   ,ScheduledExecutorService

Runnable  ,Callable,Future .

 

Executor    接口,只有一个方法void  execute(Runnable command) 执行给定的命令

Executors  类,java.uti.concurrent.Executors ,该类提供static的创建线程池的方法,截一下部分API

        

聊聊看到这些方法有一个共同点就是都是返回  ExecutorService 接口或其子接口。所以ExecutorService是用来服务 Executors的。

这里在说一下这里比较常用的两个方法  newFixThreadPool()和 newCachedThreadPool() ,

FixThreadPool:是一种线程数量固定的线程池,只有核心线程,没有超时机制,任务队列没有大小限制.

                           核心线程数 = 最大线程数

行给定的任务,当所有任务完成时,返回保持任务状态和结果的 Future 列表。                           当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来.
                            当线程处于空闲状态时,它们并不会被回收,除非线程池被关闭了.这意味着它能够更加快速的响应外界的请求.

//构造方法
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}

CacheThreadPool:

                     CachedThreadPool线程数量不定,只有非核心线程,并且其最大线程数为Integer.MAX_VALUE(相当于无限大)                                   当线程池中的线程都处于活动状态时,线程池会创建新的线程来处理新任务,否则就会利用空闲的线程来处理新任务.   

                    空闲线程都有超时时机,这个超时时长为60秒,限制超60秒就会被回收.

                     和FixedThreadPoolExecutor不同的是,CachedThreadPool的任务队列其实相当一个空集合,这将导致任何任务都会                         被立即执行,因为此时SynchronousQueue是无法插入任务的.

                      CachedThreadPool线程池比较适合执行大量+耗时较少的任务.当整个线程池都处于闲置状态时,会因超时而被停止,                        此时没有线程的线程池几乎不占用任何系统资源.

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

注意观察创建线程池的参数

接着谈谈ExecutorService ,接口,ScheduledExecutorService为其子接口

 全部api截图

       ExecutorService有个shutdown()函数,如果线程没有设置成守护线程,程序结束线程池需要用shutdown手动关闭,如果设置了守护线程则不需要。

      ExecutorService能给线程池提交任务(一个或多个)。通过其得到返回值

 关于submit()和 executor():

   1. 接收的参数不一样;

  2. submit()有返回值,而execute()没有;

    例如,有个validation的task,希望该task执行完后告诉我它的执行结果,是成功还是失败,然后继续下面的操作。

  3. submit()可以进行Exception处理;

    例如,如果task里会抛出checked或者unchecked exception,而你又希望外面的调用者能够感知这些exception并做出及时的处理,那么就需要用到submit,通过对Future.get()进行抛出异常的捕获,然后对其进行处理。

关于invokeAll() 和  invokeAny():两者从API上很难看出差别

 invokeAny():

   1. 一旦有1个任务正常完成(执行过程中没有抛异常),线程池会终止其他未完成的任务。

  2.如果提交的任务列表中,没有1个正常完成的任务,那么调用invokeAny会抛异常,究竟抛的是哪儿个任务的异常,无关紧要。

   3.先提交3个异常任务,再提交1个正常的耗时任务,不会抛出任何异常,打印出t2任务的返回结果。也就是说:invokeAny()和任务的提交顺序无关,只是返回最早正常执行完成的任务。

invokeAll():


这个方法相对来说比较好理解,就是执行任务列表中的所有任务,并返回与每个任务对应的Futue。也就是说,任务彼此之间不会相互影响,可以通过future跟踪每一个任务的执行情况,比如是否被取消,是正常完成,还是异常完成,这主要使用Future类提供的API。

最后谈一下Future类:先截API

   

用Future类来获取  ExecutorService.submit() 执行的结果;很简单

强调一下:get()方法可以当任务结束后返回一个结果,如果调用时,工作还没有结束,则会阻塞线程,直到任务执行完。

 

 

下个内容要学一下 RunnableFuture

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值