Executor 框架小结

在Java中,使用线程来异步执行任务,但是线程的创建和销毁都需要一定的开销,如果我们为每一个任务都新开一个线程来执行,必然对计算机造成巨大的压力。 从JDK 5开始,Java可以提供了将工作单元和执行机制分离开的工具,其中工作单元是实现了Runnable或者Callable接口类,而执行机制就是我们下面要讲到的Executor 框架。

Executor 框架的结构

一、任务:即工作单元,实现了Runnable或者Callable接口类;

二、任务的执行:包括了任务执行机制的核心接口Executor,以及从Executor 接口继承的ExecutorService接口,关键类包括(ThreadPoolExecutor和ScheduledThreadPoolExecutor)

三、任务异步执行的结果:对接口的获取,包括接口Future和实现了Future接口的子类FutureTask类

关于任务,由于只要实现了Runnable或者Callable接口类就可以作为一个任务,因此这边就不在叙述了,我们主要着重后面的两点。

任务的执行:

1、ThreadPoolExecutor:通常使用 工厂类Executors或者ExecutorService来创建(当然我们也可以手工创建),Executors或者ExecutorService可以创建

三种类型的ThreadPoolExecutor,分别是newFixedThreadPool、newSingleThreadExecutor、newCachedThreadPool。

1.1、newFixedThreadPool:

ExecutorService executorService2 = Executors.newFixedThreadPool(2);  
public static ExecutorService newFixedThreadPool(int nThreads) {  
        return new ThreadPoolExecutor(nThreads, nThreads,  
                                      0L, TimeUnit.MILLISECONDS,  
                                      new LinkedBlockingQueue<Runnable>());  
    } 
我们可以看到,我们可以指定corePoolSize、maximumPoolSize,并且指定他们的值时一样的,并且空线程的被回收时间为0S,为什么要这样设计呢?原来它使用的是LinkedBlockingQueue默认的大小(即无限大),这时候我们可以任务它是个无界数组,当线程数大于corePoolSize时,后面的线程都被阻塞在了LinkedBlockingQueue队列中,因此其他的几个参数都因此失效了。
1.2、newSingleThreadExecutor:
ExecutorService executorService = Executors.newSingleThreadExecutor();  
public static ExecutorService newSingleThreadExecutor() {  
        return new FinalizableDelegatedExecutorService  
            (new ThreadPoolExecutor(1, 1,  
                                    0L, TimeUnit.MILLISECONDS,  
                                    new LinkedBlockingQueue<Runnable>()));  
    }  
Single,顾名思义:单个的,因此它只有一个线程在执行,参数都与LinkedBlockingQueue差不多,适用于需要保证先进先出按照顺序执行各个任务,并且不会有多个线程是活动的场景。
1.3、newCachedThreadPool:

ExecutorService executorService3 = Executors.newCachedThreadPool();  
public static ExecutorService newCachedThreadPool() {  
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,  
                                      60L, TimeUnit.SECONDS,  
                                      new SynchronousQueue<Runnable>());  
    } 
我们分析一下参数:corePoolSize = 0,核心线程数为0,说明有任务提交给executorService3,就会进入阻塞队列,而最后一个参数是SynchronousQueue,此阻塞队列只能 包含阻塞一个任务,由于maximumPoolSize = Integer.MAX_VALUE,因此其他任务都会被新建线程来执行。假如主线程提交任务的速度高于maximumPoolSize 中的线程处理 任务的速度时,就会不断的产生线程,从而耗尽CPU资源和内存资源。另外newCachedThreadPool中线程处理完任务后,线程空闲的时间为60秒,超过这个时间的空闲线程, 将会被回收。
2、ScheduledThreadPoolExecutor

ScheduledThreadPoolExecutor继承自ThreadPoolExecutor,由名字中Scheduled(将…列入计划(或时间)表)单词可以看出,这个是一个和时间相关的线程池,主要是用来在给定的延迟之后运行任务,或者定期执行任务;

ExecutorService executorService4 = Executors.newScheduledThreadPool(3);  
public ScheduledThreadPoolExecutor(int corePoolSize) {  
        super(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.NANOSECONDS,  
              new DelayedWorkQueue());  
    }  

我们先来分析一下参数:corePoolSize 可以进行自定义,说明有任务提交给executorService3,线程数大于corePoolSize时,就会进入阻塞队列,而最后一个参数是DelayedWorkQueue,此阻塞队列是 无界队列,因此参数Integer.MAX_VALUE不起任何作用。
今天有点晚了,明天晚上继续更新。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值