ExecutorService

ExecutorService 是Excutor 的子接口,在内部添加了比较多的方法。 AbstractExecutorService抽象类 是它的唯一子实现类。ThreadPoolExecutor是 AbstractExecutorService 子类

一:Executors 工厂类创建线程池 (有4种不同的线程池对象):

1:通过Executors类的newCachedThreadPool() 创建的是无界线程池:

ExecutorService executorService = Executors.newCachedThreadPool()

缓存型池子,先查看池中有没有以前建立的线程,如果有,就 reuse(再用),如果没有 就建一个新的线程加入池中, 缓存型池子通常用于执行一些生存期很短的异步型任务。不适用于IO等长延时操作,因为这可能会创建大量线程,导致系统崩溃。 使用SynchronousQueue作为阻塞队列,如果有新任务进入队列,必须队列中数据被其他线程处理,否则会等待

2:方法 newFixedThreadPool(int) 创建的是有界线程池

也是能 再利用(reuse) 就用,但不能随时建立新的线程。独特之处是: 任意时间点,最多只能有固定 数目的活动线程存在,此时如果有新的线程要建立,只能放在另外的队列中等待,知道当前的线程中某个线程终止直接被移出池子。 使用无界的LinkedBlockingQueue要综合考虑生成与消费能力,生成过剩,可能导致堆内存溢出 适用一些很稳定固定的正规并发线程,多用于服务器。

3:ScheduledThreadPool 调度型线程池

这个池子里的线程可以按 schedule 依次 delay 执行,或周期执行支持定时及周期性任务执行)

4: SingleThreadExecutor 单例线程

任意时间中只能有一个线程, 用的是和cache 池,fixed 池 相同的底层池适用于有明确执行顺序但是不影响主线程的任务,压入池中的任务会按照队列顺序执行

 

二: 主要参数如下

corePoolSize

池中所保存的线程数,包括空闲线程,就是 核心池的大小;(相当于是:标准数)

1,如果池中线程数量少于核心线程池数量,则直接新建线程处理当前任务;

2,核心线程池空闲不会被回收

3,当池中无空闲线程时,新任务将被添加到阻塞队列

maximumPoolSize

池中允许的最大线程数(相当于是:最大负载数)

1,当阻塞队列已满,并且有新任务还在入队时,创建新的线程处理,直到线程数大于 maximumPoolSize

2,超出corePoolSize 部分的线程超过空余时间后会被回收。

3,当线程超过corePoolSize ,并且队列容量已满,则拒绝入列。

keepAliveTime

当线程数量大于 corePoolSize 值时,在没有超过指定的时间内是不从线程池中将空闲线程删除的,如果超过此时间单位则删除

1,当线程超出 corePoolSize 时 生效。

2,当线程空余 keepAlive Time 后,将被回收

unit

keepAliveTime 参数的时间单位

workQueue

线程使用阻塞队列,执行前 用于保持任务的队列,此队列仅保持由 execute 方法提交的Runnable 任务

三:在使用线程池的过程中大部分会出现5种情况:

1:如果 execute(runnable)预执行的数量 < corePoolSize,那么马上创建线程运行这个任务,并不放入扩展队列Queue 中,其它参数功能忽略;

2:如果 execute(runnable)预执行的数量 > corePoolSize,

并且 execute(runnable)预执行的数量 <= maximumPoolSize,

并且 new LinkedBlockingDeque<Runnable>;队列,无构造参数

则 maximumPoolSize 和 keepAliveTime 忽略,并把 多出的任务放入改队列等待

3:如果 execute(runnable)预执行的数量 > corePoolSize,

并且 execute(runnable)预执行的数量 <= maximumPoolSize,

并且 new SynchronousQueue(Runnable)队列,

则 maximumPoolSize 和 keepAliveTime 有效,并马上创建线程运行这些任务,而不把多出的任务放入该队列,多出的任务执行完后,在指定时间后发生超时时 将多出的任务进行清除;

4:如果 execute(runnable)预执行的数量 > corePoolSize,

并且 execute(runnable)预执行的数量 > maximumPoolSize,

并且 new LinkedBlockingDeque<Runnable>;队列,无构造参数 ,

则 maximumPoolSize 和 keepAliveTime 忽略,并把 多出的任务放入改队列等待执行

5:如果 execute(runnable)预执行的数量 > corePoolSize,

并且 execute(runnable)预执行的数量 > maximumPoolSize,

并且 new SynchronousQueue(Runnable)队列,

则处理maximumPoolSize 的任务,其它任务则不再处理,抛出异常

6:参数 keepAliveTime 为 0 时,:当线程数大于 corePoolSize 值时,在没有超过指定的时间内 是不从线程池中奖的空闲线程删除的,如果超过此时间单位,则删除。如果为 0 则任务执行完毕后立即从队列中删除。

 

四:线程池的五种状态

1、RUNNING

(1) 状态说明:线程池处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理。

(2) 状态切换:线程池的初始化状态是RUNNING。换句话说,线程池被一旦被创建,就处于RUNNING状态,并且线程池中的任务数为0

2、 SHUTDOWN

(1) 状态说明:线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务。

(2) 状态切换:调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN。

3、STOP

(1) 状态说明:线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务

(2) 状态切换:调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP

4、TIDYING

(1) 状态说明:当所有的任务已终止,ctl记录的”任务数量”为0,线程池会变为TIDYING状态。当线程池变为TIDYING状态时,会执行钩子函数terminated()。terminated()在ThreadPoolExecutor类中是空的,若用户想在线程池变为TIDYING时,进行相应的处理;可以通过重载terminated()函数来实现。

(2) 状态切换:当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING。

当线程池在STOP状态下,线程池中执行的任务为空时,就会由STOP -> TIDYING。

5、 TERMINATED

(1) 状态说明:线程池彻底终止,就变成TERMINATED状态。

(2) 状态切换:线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED

 

五:线程池ThreadPoolExecutor 的拒绝策略

线程池中的资源全部被占用时,对新添加的Task任务有不同的处理策略,在默认情况下,有四种不同的处理方式:

AbortPolicy:当任务添加到线程池中被拒绝时,它将抛出RejectedExcutionExceptiony异常;

CallerRunPolicy:当任务添加到线程池中被拒绝时,会使用调用线程的Thread线程对象处理被拒绝的任务;

DiscardOldestPolicy:当任务添加到线程池中被拒绝时,线程池会放弃等待队列中最旧的未处理任务,然后将被拒绝的任务添加到等待队列中。

DiscardPolicy:当任务添加到线程池中被拒绝时,线程池将丢弃被拒绝的任务。

 

六:相关方法

shutdown() 方法:

1:当调用该方法后,线程池的状态则立刻变成 SHUTDOWN 状态,而不再添加新的任务Task,否则就会抛出 RejectedExecutionException (拒绝异常),但是此时线程池不会立即退出,直到线程池中的任务都已处理完成,才会退出。

2:该方法不会阻塞,调用该方法后,主线程main 就马上结束了,而线程池会继续执行直到所有任务执行完成才会停止。如果不调用该方法,那么线程池会一直保持下去,以便随时执行被添加的新 Task 任务。 XX在关闭 ExcutorServcie 之前等待提交的任务执行完成

shutdownNow() 方法:

1:该方法是使线程池的状态立刻变成 STOP 状态,会阻止开启新的任务并且尝试停止当前正在执行的线程(如果有if判断则人为的抛出异常)

2:一旦调用该方法,不再处理还在池队列中等待的任务,也没有新任务提交 。当然,它会返回那些未执行的任务

isShutdown()方法 判断线程池是否已经关闭

 

isTerminating() 和 isTerminated():

1:如果正在执行的程序处于 shutdown ,或 shutdownNow之后处于正在终止但尚未完全终止的过程中,调用 isTerminating() 则返回 true ,此方法可以比喻成: 门是否在关闭。门彻底关闭时,线程池也就关闭了。

2:如果线程池关闭后,也就是所有任务都已完成,则方法 isTerminated()返回 true。此方法 可以比喻成:门是否关闭。

 

awaitTermination(Long timeout,TimeUnit unit)

查看在指定的时间内,线程池是否已经终止工作,也就是最多等待多少时间后去判断线程池是否已终止工作

方法 awaitTermination() 和 shutdown() 结合时,可以实现 “等待执行完毕”的效果,原理就是应用awaitTermination()方法具有阻塞性

 

afterExecute() 和 beforeExecute()

在线程池ThreadPoolExecutor 类中重写这两个方法,可以对线程池中执行的线程对象实现监控。

remove(Runnable()) 可以删除尚未被执行的Runnable 任务

 

getAlivieCount() 取得有多少个线程正在执行任务

 

 

 

七:区别

submit() 和 callable() :

1:方法 execute() 没有返回值,而submit()方法可以有返回值

2:方法 execute() 在默认情况下异常直接抛出,不能捕获,但可以通过自定义 ThreadFactory 的方式进行捕获,而submit() 方法在默认的情况下,可以 catch ExecutionException 捕获异常

 

Callable和Runnable :

1:Callable 接口的 call()方法可以有返回值,而Runnable接口的 run() 方法没有返回值。

2:Callable 接口的 call() 方法可以声明抛出异常,而 Runnable 接口的 run() 方法不可以。

执行完 Callable 接口中的任务后,返回值是通过 Future 接口进行获得。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值