`
Donald_Draper
  • 浏览: 992337 次
社区版块
存档分类
最新评论

ScheduledThreadPoolExecutor解析三(关闭线程池)

    博客分类:
  • JUC
阅读更多
ScheduledThreadPoolExecutor解析一(调度任务,任务队列):
http://donald-draper.iteye.com/blog/2367332
ScheduledThreadPoolExecutor解析二(任务调度):
http://donald-draper.iteye.com/blog/2367593
前面一篇文章,我们看了任务的调度,先回顾一下:
从调度线程池执行器的构造来看,核心线程池数量是必须设置的,线程工厂和拒绝策略可选,默认最大线程池数量为 Integer.MAX_VALUE,保活时间为0,即不存在空闲的任务线程,
任务队列为DelayedWorkQueue。
     scheduleAtFixedRate方法首先根据任务command和任务执行系统时间,
及任务间隔时间period,构造调度任务,简单包装调度任务,延时执行调度任务,
延时执行调度任务。在延时执行调度任务时,
添加任务到延时DelayedWorkQueue,同时添加一个空任务工作线程,空任务工作线程执行时,
如果任务为null,则从任务队列中取任务。调度任务的执行,如果任务为ScheduledFutureTask,
在运行的时候,从新计算任务下一次执行的系统时间,重置任务线程状态为READY,添加任务到队列。
     scheduleWithFixedDelay与scheduleAtFixedRate不同点在构造ScheduledFutureTask时间间隔为-delay。时间间隔p为正,以固定的频率调度任务即scheduleAtFixedRate,每隔p时间执行一次任务,无论上一次任务是否执行完,具体任务能否执行,调度线程池无法保证,这要看是否有工作线程可用;当时间间隔p为负,以固定的间隔时间调度任务,即scheduleWithFixedDelay,
当前任务执行完后,等待p时间,再执行下一个任务。
今天来看一下线程池的关闭。
public void shutdown() {
        //委托给父类线程池执行器
        super.shutdown();
    }

//ThreadPoolExecutor
 public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
	    //检查线程访问权限
            checkShutdownAccess();
	    //更新线程池状态为SHUTDOWN
            advanceRunState(SHUTDOWN);
	    //中断空闲工作线程
            interruptIdleWorkers();
	    //线程池关闭hook
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
	//尝试结束线程池,这个前面以说,这里不再说
        tryTerminate();
}

关键在这一点
//线程池关闭hook
onShutdown(); // hook for ScheduledThreadPoolExecutor


 /**
  * Cancels and clears the queue of all tasks that should not be run
  * due to shutdown policy.  Invoked within super.shutdown.
  */
 @Override void onShutdown() {
     //获取任务队列
     BlockingQueue<Runnable> q = super.getQueue();
     boolean keepDelayed =
         getExecuteExistingDelayedTasksAfterShutdownPolicy();
     boolean keepPeriodic =
         getContinueExistingPeriodicTasksAfterShutdownPolicy();
     if (!keepDelayed && !keepPeriodic) {
          //如果在线程池关闭时,可以在任务执行时,取消间歇性任务和延时任务,
	  //则遍历任务,并以不可中断方式取消任务。
         for (Object e : q.toArray())
             if (e instanceof RunnableScheduledFuture<?>)
                 ((RunnableScheduledFuture<?>) e).cancel(false);
         q.clear();
     }
     else {
         // Traverse snapshot to avoid iterator exceptions
	 //否则,遍历任务根据是间歇性任务还是延时任务,
	 //获取相应的线程池关闭是否可取消正在执行的任务的策略
         for (Object e : q.toArray()) {
             if (e instanceof RunnableScheduledFuture) {
                 RunnableScheduledFuture<?> t =
                     (RunnableScheduledFuture<?>)e;
                 if ((t.isPeriodic() ? !keepPeriodic : !keepDelayed) ||
                     t.isCancelled()) { // also remove if already cancelled
		     如果可取消或任务已经取消,则移除任务,成功,则以不可中断方式取消任务。
                     if (q.remove(t))
                         t.cancel(false);
                 }
             }
         }
     }
     //这个在线程池相关的文章中以说,这里不再说,尝试关闭线程池
     tryTerminate();
 }

关闭操作,与线程池执行器的关闭基本相同,不同的是,在onShutdown方法,调度线程池执行器,重写了这个方法,这个方法主要是根据线程池关闭间歇性任务和延时任务的处理策略,确定是否以不可中断方式取消任务。

再来看立即关闭:
 public List<Runnable> shutdownNow() {
        //委托给父类
        return super.shutdownNow();
    }

//执行Runnable任务
public void execute(Runnable command) {
        schedule(command, 0, TimeUnit.NANOSECONDS);
    }
//提交Runnable任务
    // Override AbstractExecutorService methods

    /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public Future<?> submit(Runnable task) {
        return schedule(task, 0, TimeUnit.NANOSECONDS);
    }

    /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public <T> Future<T> submit(Runnable task, T result) {
        return schedule(Executors.callable(task, result),
                        0, TimeUnit.NANOSECONDS);
    }

    /**
     * @throws RejectedExecutionException {@inheritDoc}
     * @throws NullPointerException       {@inheritDoc}
     */
    public <T> Future<T> submit(Callable<T> task) {
        return schedule(task, 0, TimeUnit.NANOSECONDS);
    }
//设置线程池关闭延时任务处理策略
 /**
  * Sets the policy on whether to execute existing delayed
  * tasks even when this executor has been {@code shutdown}.
  * In this case, these tasks will only terminate upon
  * {@code shutdownNow}, or after setting the policy to
  * {@code false} when already shutdown.
  * This value is by default {@code true}.
  *
  * @param value if {@code true}, execute after shutdown, else don't.
  * @see #getExecuteExistingDelayedTasksAfterShutdownPolicy
  */
 public void setExecuteExistingDelayedTasksAfterShutdownPolicy(boolean value) {
     executeExistingDelayedTasksAfterShutdown = value;
     if (!value && isShutdown())
         //如果在线程池关闭时,可以取消延时任务
         onShutdown();
 }
//设置线程池关闭间歇性任务处理策略
 /**
  * Sets the policy on whether to continue executing existing
  * periodic tasks even when this executor has been {@code shutdown}.
  * In this case, these tasks will only terminate upon
  * {@code shutdownNow} or after setting the policy to
  * {@code false} when already shutdown.
  * This value is by default {@code false}.
  *
  * @param value if {@code true}, continue after shutdown, else don't.
  * @see #getContinueExistingPeriodicTasksAfterShutdownPolicy
  */
 public void setContinueExistingPeriodicTasksAfterShutdownPolicy(boolean value) {
     continueExistingPeriodicTasksAfterShutdown = value;
     if (!value && isShutdown())
          //如果在线程池关闭时,可以取消间歇性任务
         onShutdown();
 }

总结:
关闭操作,与线程池执行器的关闭基本相同,不同的是,在onShutdown方法,调度线程池执行器,重写了这个方法,这个方法主要是根据线程池关闭间歇性任务和延时任务的处理策略,确定是否以不可中断方式取消任务。
0
0
分享到:
评论

相关推荐

    JAVA课程学习笔记.doc

    本篇学习笔记将深入解析Java线程池的框架、结构、原理以及相关源码,帮助读者全面理解线程池的工作机制。 1. 线程池模块结构 线程池框架分为多层结构,其中包括核心实现类、辅助类和接口等组件。例如,`sun.nio.ch....

    线程池介绍

    本篇将详细介绍安卓线程池的四种使用方法,并结合具体源码进行解析。 一、ThreadPoolExecutor的创建与使用 ThreadPoolExecutor是Java中的线程池实现类,同样适用于安卓开发。通过指定核心线程数、最大线程数、线程...

    concurrent-all-in-one.pdf

    - ScheduledThreadPoolExecutor:支持定时任务的线程池。 - ForkJoinPool:适用于分治算法,利用工作窃取原理提高并发性能。 13. **Fork/Join框架** - ForkJoinPool:处理并行任务的线程池。 - ForkJoinTask:...

    threadmodel:java线程模型

    1. **Java线程基础**:包括线程的创建、启动、同步控制(如synchronized、wait/notify、Lock接口等)以及线程池的使用(如ExecutorService、ThreadPoolExecutor和ScheduledThreadPoolExecutor)。 2. **BIO线程模型...

    java编程思想参考答案

    - 线程池:了解ExecutorService、ThreadPoolExecutor和ScheduledThreadPoolExecutor的作用。 6. **I/O流** - 文件流:掌握FileInputStream和FileOutputStream的基本用法。 - 字符流:理解Reader和Writer的区别,...

    Memologue:提醒自己做周期性任务

    以下将详细解析这些关键知识点: 1. **线程处理**:Java中的线程机制是实现定时任务的基础。在Memologue中,应用创建一个后台线程来执行任务检查和提醒功能,避免因长时间运行任务而阻塞主线程,影响用户体验。Java...

Global site tag (gtag.js) - Google Analytics