`
XTU_xiaoxin
  • 浏览: 237264 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA线程池shutdown和shutdownNow的区别

    博客分类:
  • JAVA
阅读更多
         shutDown()

    当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中添加任何任务,否则将会抛出RejectedExecutionException异常。但是,此时线程池不会立刻退出,直到添加到线程池中的任务都已经处理完成,才会退出。

            shutdownNow()

     根据JDK文档描述,大致意思是:执行该方法,线程池的状态立刻变成STOP状态,并试图停止所有正在执行的线程,不再处理还在池队列中等待的任务,当然,它会返回那些未执行的任务。
     它试图终止线程的方法是通过调用Thread.interrupt()方法来实现的,但是大家知道,这种方法的作用有限,如果线程中没有sleep 、wait、Condition、定时锁等应用, interrupt()方法是无法中断当前的线程的。所以,ShutdownNow()并不代表线程池就一定立即就能退出,它可能必须要等待所有正在执行的任务都执行完成了才能退出。

    上面对shutDown()以及shutDownNow()作了一个简单的、理论上的分析。如果想知道why,则需要亲自打开JDK源码,分析分析。
      想要分析shutDown()以及shutDownNow()源码,我建议首先要对ThreadPoolExecutor有个大概了解。因为关闭线程池的所有方法逻辑都在ThreadPoolExecutor中处理的。
      如果你真的想知道为什么,建议看一下我以前写的一篇对ThreadPoolExecutor源码分析的博文,我想这对你比较透彻的了解shutDown()和shutDownNow()的区别以及java 线程池原理有很大的帮助。博文URL:
         http://xtu-xiaoxin.iteye.com/admin/blogs/647744

     废话少说,要查看源码,首先进入ThreadPoolExecutor的shutDown()方法:


  
public void shutdown() {
	 SecurityManager security = System.getSecurityManager();
	if (security != null)
            security.checkPermission(shutdownPerm);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (security != null) { // Check if caller can modify our threads
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            }
            int state = runState;
            if (state < SHUTDOWN)
            	//设置线程池状态为关闭状态
                runState = SHUTDOWN;     //----------------代码1
            try {
                for (Worker w : workers) {
                	//一个一个中断线程
                    w.interruptIfIdle();  //-----------------代码2
                }
            } catch (SecurityException se) { // Try to back out
                runState = state;
                // tryTerminate() here would be a no-op
                throw se;
            }
            tryTerminate(); // Terminate now if pool and queue empty
        } finally {
            mainLock.unlock();
        }
    }


  看上面源码,代码1是线程池关闭的关键,如果线程池状态一旦设为SHUTDOWN,则在线程池中会出现两种现象:
     1.你不能再往线程池中添加任何任务,否则会抛RejectedExecutionException异常(详细请看ThreadPoolExecutor的addIfUnderCorePoolSize方法)。
     2.工作线程Worker获得池队列中的任务时(详细看Worker中的getTask()方法)的处理逻辑也发生了变化:如果线程池为RUNNING状态,并且池队列中没任务时,它会一直等待,直到你提交任务到池队列中,然后取出任务,返回。但是,一旦你执行了shutDown()方法,线程池状态为SHUTDOWN状态,它将不再等待了,直接返回null。如果返回null,则工作线程没有要执行的任务,直接退出(详细看Worker中run()方法)。

    代码2是针对这种情况的:在线程池关闭前,有部分工作线程就一直在等着要处理的任务,也就是说工作线程空闲着(这种情况我描述的不好,其实就是Worker正在执行getTask()方法中’ r = workQueue.take();’代码段)。这时,调用interrupt()方法来中断这些Worker线程。进入代码2看看吧:

  
 
void interruptIfIdle() {
            final ReentrantLock runLock = this.runLock;
            /*
             * 注意这个条件,摆明的就是要等Worker中runTask()方法运行完后才成立。
             * 锁机制
             */
            if (runLock.tryLock()) {
                try {
            /*
             * 如果当前工作线程没有正在运行,则中断线程
             * 他能中断工作线程的原因是getTask()方法能抛出一个
             * InterruptedException。这时,则可终止那些正在执行
             * workQueue.take()方法的工作线程
             */
		    if (thread != Thread.currentThread())
			thread.interrupt();         
                } finally {
                    runLock.unlock();
                }
            }
        }


   最后进入shutDownNow()方法看看,这个更简单了,就是设置线程池状态为STOP,然后依次调用工作线程的interrupt()方法,就这么简单,最后还是把源码贴出来吧:
   
     
 public List<Runnable> shutdownNow() {
        /*
         * shutdownNow differs from shutdown only in that
         * 1. runState is set to STOP,
         * 2. all worker threads are interrupted, not just the idle ones, and
         * 3. the queue is drained and returned.
         */
	SecurityManager security = System.getSecurityManager();
	if (security != null)
            security.checkPermission(shutdownPerm);

        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (security != null) { // Check if caller can modify our threads
                for (Worker w : workers)
                    security.checkAccess(w.thread);
            }

            int state = runState;
            if (state < STOP)
                runState = STOP;

            try {
                for (Worker w : workers) {
                    w.interruptNow();
                }
            } catch (SecurityException se) { // Try to back out
                runState = state;
                // tryTerminate() here would be a no-op
                throw se;
            }

            List<Runnable> tasks = drainQueue();
            tryTerminate(); // Terminate now if pool and queue empty
            return tasks;
        } finally {
            mainLock.unlock();
        }
    }

    上面代码没什么好分析的了,一看就明白,其实别看上面代码一大篇,我们只关心“w.interruptNow();”即可。
      还是那句话,希望对需要了解的人有点帮助。 
分享到:
评论
1 楼 makefu 2011-07-23  
    /**
     * runState provides the main lifecyle control, taking on values:
     *
     *   RUNNING:  Accept new tasks and process queued tasks
     *   SHUTDOWN: Don't accept new tasks, but process queued tasks
     *   STOP:     Don't accept new tasks, don't process queued tasks,
     *             and interrupt in-progress tasks
     *   TERMINATED: Same as STOP, plus all threads have terminated
     *
     * The numerical order among these values matters, to allow
     * ordered comparisons. The runState monotonically increases over
     * time, but need not hit each state. The transitions are:
     *
     * RUNNING -> SHUTDOWN
     *    On invocation of shutdown(), perhaps implicitly in finalize()
     * (RUNNING or SHUTDOWN) -> STOP
     *    On invocation of shutdownNow()
     * SHUTDOWN -> TERMINATED
     *    When both queue and pool are empty
     * STOP -> TERMINATED
     *    When pool is empty
     */

相关推荐

    java线程池概念.txt

    当线程池处于SHUTDOWN或STOP状态,并且所有工作线程已经销毁,任务缓存队列已经清空或执行结束后,线程池被设置为TERMINATED状态 b:参数再次说明。这是摘自网络的解释,我觉得他比喻的很好,所以这里直接就用它的...

    深入理解Java线程池:ThreadPoolExecutor _ Idea Buffer1

    1. RUNNING :能接受新提交的任务,并且也能处理阻塞队列中的任务 2. SHUTDOWN:关闭状态,不再接受新提交的任务,但却可以继续处理阻塞队列中已保

    Java线程池框架核心代码分析

    Java 通过Executor接口,提供了一种标准的方法将任务的提交过程和执行过程解耦开来,并用Runnable表示任务。  下面,我们来分析一下 Java 线程池框架的实现ThreadPoolExecutor。  下面的分析基于JDK1.7  生命...

    线程池核心组件源码剖析.docx

    该组件中,Executor 和 ExecutorService 接口 定义了线程池最核心的几个方法,提交任务 submit ()、关闭线程池 shutdown()。抽象类 AbstractExecutorService 主要对公共行为 submit()系列方法进行了实现,这些 ...

    shutdown-java.bat

    终止系统运行的java进程 主要用于windows系统下某些java运行工具下,集成此脚本进行使用。

    使用Java匿名内部类实现一个简单的线程池.txt

    这段代码实现了一个简单的线程池ExecutorService,其中使用了Java的匿名内部类。...这个简单的示例代码展示了如何使用Java匿名内部类来实现一个线程池的简单功能,方便了对多线程任务的管理和执行。

    shutdown问题

    shutdown.rar

    Java线程池介绍

    根据摩尔定律(Moore’s law),集成电路晶体管的数量差不多每两年会翻一倍。但是晶体管数量指数级的增长不一定会导致 CPU 性能的指数级增长。处理器制造商花了很多年来提高...线程池可以帮助程序员更好地利用多核 C

    shutdown.exe

    windowsxp的关机程序 shutdown.exe

    Linux上TCP的Shutdown和Close

    本文介绍了Linux上TCP的Shutdown和Close操作。

    linuxC语言线程池实现CP命令

    linux系统下C语言 利用线程池技术实现CP命令 压缩包包含:源代码+开发说明PPT 线程池头文件: //任务 struct task { void *(*task)(void *arg); void *arg; struct task *next; }; //线程池 typedef struct ...

    Linux Shutdown和 Vi命令

    Linux Shutdown和 Vi命令 !!!!!!!

    Oracle数据库startup和shutdown方式

    Oracle数据库startup和shutdown方式

    JAVA虚拟机关闭钩子(Shutdown Hook).docx

    JAVA虚拟机关闭钩子(Shutdown Hook).docx

    12行代码,使用Java的并发和多线程技术实现简单的任务调度器

    使用Java的ExecutorService类创建了一个固定大小的线程池,并将任务安排到线程池中执行。 通过调用`scheduleTask()`方法,可以指定要执行的任务、延迟时间和延迟时间单位。 任务将在指定的延迟时间后被安排到线程池...

    线程池的源代码

    int shutdown; /*线程池销毁标记*/ int max_thr_num; /*最大线程数*/ pthread_t *thr_id; //线程id数组 tpool_work_st *queue_head; //线程池队列头 pthread_mutex_t queue_lock; //线程池锁 ...

    SHUTDOWN-定时开机关机

    SHUTDOWN-定时开机关机 SHUTDOWN-定时开机关机 SHUTDOWN-定时开机关机 SHUTDOWN-定时开机关机 SHUTDOWN-定时开机关机

    Linux系统关机命令shutdown

    Linux系统关机命令shutdown introduction

    ORACLE 启动过程、shutdown 和 startup 参数说明

    ORACLE 启动过程、shutdown 和 startup 参数说明 都有比较详细的说明,是自己整理的。

    ShutDown Expert

    ShutDown Expert ShutDown Expert ShutDown Expert

Global site tag (gtag.js) - Google Analytics