Java线程与Android线程,Android线程篇(三):深入理解Java线程池(一)

上篇文章我们讲解了Java的四种线程池,我们知道如何去使用四种线程池,以及在合适的情况下使用合适的线程池,常言道,不懂原理的厨师不是好的程序员,所以本篇文章,就带大家一起去探寻Java线程池的秘密。

1.我们来先看看四种线程池的源码

newFixedThreadPool

public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) {

return new ThreadPoolExecutor(nThreads, nThreads,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue(),

threadFactory);

}

返回了ThreadPoolExecutor对象

newSingleThreadExecutor

public static ExecutorService newSingleThreadExecutor() {

return new FinalizableDelegatedExecutorService

(new ThreadPoolExecutor(1, 1,

0L, TimeUnit.MILLISECONDS,

new LinkedBlockingQueue()));

}

返回了ThreadPoolExecutor对象

newCachedThreadPool

public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) {

return new ThreadPoolExecutor(0, Integer.MAX_VALUE,

60L, TimeUnit.SECONDS,

new SynchronousQueue(),

threadFactory);

}

返回了ThreadPoolExecutor对象

newScheduledThreadPool

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {

return new ScheduledThreadPoolExecutor(corePoolSize);

}

返回了ScheduledThreadPoolExecutor对象,那我们再来看看ScheduledThreadPoolExecutor的源码

public class ScheduledThreadPoolExecutor

extends ThreadPoolExecutor

implements ScheduledExecutorService {

ScheduledThreadPoolExecutor又继承了ThreadPoolExecutor对象

so,没有意外,没有惊喜,还是返回了ThreadPoolExecutor对象

既然每个线程池都返回了ThreadPoolExecutor,貌似好神奇啊,那我们就来看看这是个什么玩意儿,看看到底有多神奇,到底有没有意外,到底有没有惊喜,哈哈……

通过观察ThreadPoolExecutor源码,我们发现:

ThreadPoolExecutor 继承自AbstractExecutorService

public class ThreadPoolExecutor extends AbstractExecutorService {

ThreadPoolExecutor提供了四种构造方法

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueueworkQueue) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

Executors.defaultThreadFactory(), defaultHandler);

}

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueueworkQueue,

ThreadFactory threadFactory) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

threadFactory, defaultHandler);

}

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueueworkQueue,

RejectedExecutionHandler handler) {

this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,

Executors.defaultThreadFactory(), handler);

}

public ThreadPoolExecutor(int corePoolSize,

int maximumPoolSize,

long keepAliveTime,

TimeUnit unit,

BlockingQueueworkQueue,

ThreadFactory threadFactory,

RejectedExecutionHandler handler) {

if (corePoolSize < 0 ||

maximumPoolSize <= 0 ||

maximumPoolSize < corePoolSize ||

keepAliveTime < 0)

throw new IllegalArgumentException();

if (workQueue == null || threadFactory == null || handler == null)

throw new NullPointerException();

this.corePoolSize = corePoolSize;

this.maximumPoolSize = maximumPoolSize;

this.workQueue = workQueue;

this.keepAliveTime = unit.toNanos(keepAliveTime);

this.threadFactory = threadFactory;

this.handler = handler;

}

仔细观察这个四个构造器,我们发现,前三个构造器都是调用第四个构造器来进行初始化的,所以我们要着重研究最后一个构造器,下面解释下一下构造器中各个参数的含义:

corePoolSize:核心线程池大小,创建了线程池后,默认情况下,线程池中没有任何线程(注意:是默认情况哦,证明还是其他情况哦),而是等待有任务到来才创建线程去执行任务,当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中;

maximumPoolSize:线程池最大线程数,它表示在线程池中最多能创建多少个线程;

keepAliveTime:表示线程池中的线程没有任务执行时最多保持多久时间会终止。默认,只有当线程池中的线程数大于corePoolSize时,keepAliveTime才会起作用,直到线程池中的线程数不大于corePoolSize,即当线程池中的线程数大于corePoolSize时,如果一个线程空闲的时间达到keepAliveTime,则会终止,直到线程池中的线程数不超过corePoolSize。但是如果调用了allowCoreThreadTimeOut(boolean)方法,在线程池中的线程数不大于corePoolSize时,keepAliveTime参数也会起作用,直到线程池中的线程数为0;

unit:参数keepAliveTime的时间单位,有7种取值,在TimeUnit类中有7种静态属性:

TimeUnit.DAYS //天

TimeUnit.HOURS //小时

TimeUnit.MINUTES //分钟

TimeUnit.SECONDS //秒

TimeUnit.MILLISECONDS //毫秒

TimeUnit.MICROSECONDS //微秒

TimeUnit.NANOSECONDS //纳秒

-workQueue:一个阻塞队列,用来存储等待执行的任务,线程池的排队策略与BlockingQueue有关。

我们回到上面四种线程池源码看看,发现:

newFixedThreadPool使用了LinkedBlockingQueue

newSingleThreadExecutor使用了LinkedBlockingQueue

newCachedThreadPool使用了SynchronousQueue

threadFactory:这个很好理解,字面意思就可以理解,主要用来创建线程;

handler:RejectedExecutionHandler拒绝执行处理程序,当拒绝处理任务时的策略,有以下四种取值:

1.ThreadPoolExecutor.AbortPolicy():

private static final RejectedExecutionHandler defaultHandler =

new AbortPolicy();

AbortPolicy()源码:

/**

* A handler for rejected tasks that throws a

* {@code RejectedExecutionException}.

*/

public static class AbortPolicy implements RejectedExecutionHandler {

/**

* Creates an {@code AbortPolicy}.

*/

public AbortPolicy() { }

/**

* Always throws RejectedExecutionException.

*

* @param r the runnable task requested to be executed

* @param e the executor attempting to execute this task

* @throws RejectedExecutionException always

*/

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

throw new RejectedExecutionException("Task " + r.toString() +

" rejected from " +

e.toString());

}

}

阅读源码,得出结论:AbortPolicy()会丢弃当前任务并抛出RejectedExecutionException异常

2.ThreadPoolExecutor.DiscardPolicy()

DiscardPolicy()源码:

/**

* A handler for rejected tasks that silently discards the

* rejected task.

*/

public static class DiscardPolicy implements RejectedExecutionHandler {

/**

* Creates a {@code DiscardPolicy}.

*/

public DiscardPolicy() { }

/**

* Does nothing, which has the effect of discarding task r.

*

* @param r the runnable task requested to be executed

* @param e the executor attempting to execute this task

*/

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

}

}

阅读源码,得出结论:DiscardPolicy()会丢弃当前任务但不抛出异常

3.ThreadPoolExecutor.DiscardOldestPolicy()

DiscardOldestPolicy()源码:

/**

* A handler for rejected tasks that discards the oldest unhandled

* request and then retries {@code execute}, unless the executor

* is shut down, in which case the task is discarded.

*/

public static class DiscardOldestPolicy implements RejectedExecutionHandler {

/**

* Creates a {@code DiscardOldestPolicy} for the given executor.

*/

public DiscardOldestPolicy() { }

/**

* Obtains and ignores the next task that the executor

* would otherwise execute, if one is immediately available,

* and then retries execution of task r, unless the executor

* is shut down, in which case task r is instead discarded.

*

* @param r the runnable task requested to be executed

* @param e the executor attempting to execute this task

*/

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

if (!e.isShutdown()) {

e.getQueue().poll();

e.execute(r);

}

}

}

}

再来看看e.getQueue().poll()是干什么的,来上源码:

/**

* Retrieves and removes the head of this queue,

* or returns {@code null} if this queue is empty.

*

* @return the head of this queue, or {@code null} if this queue is empty

*/

E poll();

Retrieves and removes the head of this queue, or returns {@code null} if this queue is empty:如果此队列为空,则检索并删除此队列的头部,或返回{@ code null}

阅读源码,得出结论:DiscardOldestPolicy()会丢弃队列最前面的任务,然后重新尝试执行新任务。简单来说就是:抛弃旧任务,执行新任务

4.ThreadPoolExecutor.CallerRunsPolicy()

/**

* A handler for rejected tasks that runs the rejected task

* directly in the calling thread of the {@code execute} method,

* unless the executor has been shut down, in which case the task

* is discarded.

*/

public static class CallerRunsPolicy implements RejectedExecutionHandler {

/**

* Creates a {@code CallerRunsPolicy}.

*/

public CallerRunsPolicy() { }

/**

* Executes task r in the caller's thread, unless the executor

* has been shut down, in which case the task is discarded.

*

* @param r the runnable task requested to be executed

* @param e the executor attempting to execute this task

*/

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

if (!e.isShutdown()) {

r.run();

}

}

}

阅读源码,得出结论:CallerRunsPolicy ()会重新添加当前的任务,他会自动重复调用execute()方法

文章开头不久我们发现,ThreadPoolExecutor 继承自AbstractExecutorService,那么我们下篇文章就来扒光它的衣服,看看它真实的样子……

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值