ThreadPoolExecutor源码分析一

 
     在线程池出现之前,每次需要使用线程,都得创建一个线程。但是,在java的运行环境中,创建一个线程是非常耗费资源和时间的。是否可以把线程重复利用,减少线程的创建次数。基于此,java1.5中引入了java的线程池管理。试想如果让你来实现一个线程池的管理,你会怎么实现呢?
 
     下面详细分析java ThreadPoolExecutor类的线程池原理。
 
      线程池ThreadPoolExecutor的使用方,调用方式,是把任务提交到线程池,具体线程的创建和执行是透明的。ThreadPoolExecutor有两部分组成,一个是工作线程列表,另一个是等待队列。
      一个执行任务加入线程池,可简化成下面三种情况。
     1 当工作线程没有打到设定的最大线程数时,线程池将创建一个工作线程来执行任务。
     2 当工作线程已经达到设定的最大线程时,任务将放入等待队列。
     3 当工作线程已经达到设定的最大线程时,队列也排满后,加入的任务将被拒绝
 
     ThreadPoolExecutor 有四个构造方法
 
构造方法一:
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

 

 
构造方法二:
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

 

 
构造方法三:
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

 

 
构造方法四:
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              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;
    }

 

 
参数说明
     int corePoolSize: 线程池启动后,核心线程最大数;当线程数小于corePoolSize时,加入一个任务,就创建一个线程
     BlockingQueue<Runnable> workQueue: 当线程池的线程数达到corePoolSize后,新加入的任务将被加入到队列workQueue中,线程池中的线程执行完任务后,从workQueue中取任务执行
     int maximumPoolSize:当线程池的线程数已经达到corePoolSize之后,workQueue的长度也已经放满之后,线程数继续增加,直到达到maximumPoolSize。所以上面构造方法里要求 maximumPoolSize < corePoolSize 是不被允许的。
     long keepAliveTime:线程的空闲时间,TimeUnit unit是他的时间单位。当线程池中的线程数趋于corePoolSize和maximumPoolSize之间,线程的空闲时间达到keepAliveTime,将被回收。知道线程数降到corePoolSize数之后,就不在回收。如果用户调用方法allowsCoreThreadTimeOut()之后,如果线程空闲时间达到keepAliveTime,线程仍然能被回收
     ThreadFactory threadFactory:创建线程的工厂类
     RejectedExecutionHandler handler:是在线程池已经不能在创建线程了,workQueue队列也已经满了之后,在添加任务之后的拒绝策略。
 
   前面三个构造方法,实际上都会调用到最后一个构造方法。前面三个构造方法和最后一个方法的不同在部分参数没有开放出去,采用了默认值的形式。这是我们一贯的模式,一个主的构造方法,其他构造方法在他上面构建多样化,很多参数都可以采用默认方式,设计出符合各种场景的构造方法。
 
上面列的参数中,有两个参数可以采用默认值  ThreadFactory threadFactory,  RejectedExecutionHandler handler ;  构造方法一中,这两个参数都没传入,使用默认值;构造方法二中, RejectedExecutionHandler handler没传入,使用默认值; 构造方法三中 ThreadFactory threadFactory没传人,使用默认值。
 
这里先谈下线程池已经不在接收任务时,他的拒绝策略分析。有四种策略, CallerRunsPolicy、AbortPolicy、DiscardPolicy、DiscardOldestPolicy,AbortPolicy是线程池的默认拒绝策略。
 
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拒绝策略,线程池不能在接收任务后,只要线程池没有关闭,添加任务的线程将负责任务的执行
 
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
 
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拒绝策略,线程池不能在接收任务后,再次添加,什么都不做
 
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);
            }
        }
    }

 

 
DiscardOldestPolicy拒绝策略,线程池不能在接收任务后,再次添加,将会从队列头部去掉一个任务,把新任务加入队列。
 
上面四个策略,根据具体场景来使用,也可以使用默认策略AbortPolicy。
 
其他分析接下文 《ThreadPoolExecutor源码分析二》 
 

转载于:https://www.cnblogs.com/sten/p/5678508.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值