`
XTU_xiaoxin
  • 浏览: 239626 次
  • 性别: 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线程池使用后到底要关闭吗

    java线程池是一种高效的并发编程技术,可以帮助开发者更好地管理线程资源,提高系统的性能和可靠性。然而,在使用java线程池时,一个常见的问题是:使用完线程池后到底要不要关闭?本文将通过实例代码和详细解释,...

    java线程池封装j

    5. **关闭线程池**:提供`shutdown()`或`shutdownNow()`方法,用于优雅地关闭线程池。 ### 4. 线程池优化 线程池的性能优化主要涉及以下方面: - **选择合适的工作队列**:无界队列可能导致资源耗尽,有界队列能...

    java线程池实例详细讲解

    5. **生命周期管理**:线程池提供了一些方法来控制其生命周期,如`execute()`用于提交任务,`shutdown()`用于关闭线程池但不立即停止所有正在执行的任务,而`shutdownNow()`则尝试停止所有正在执行的任务并关闭...

    java线程池实例

    Java线程池是一种高效管理线程资源的工具,它通过维护一组可重用的线程来减少创建和销毁线程的开销。在Java中,`java.util.concurrent`包提供了`ExecutorService`接口和它的实现类,如`ThreadPoolExecutor`,来支持...

    java 线程池实现多并发队列后进先出

    Java线程池是一种高效管理并发任务的机制,它允许开发者预先配置一定数量的线程,以便在处理多个并发任务时能有效地复用这些线程,从而避免了频繁创建和销毁线程带来的开销。在Java中,`java.util.concurrent`包下的...

    JAVA线程池例子

    Java线程池是一种高效管理线程资源的技术,它允许开发者创建一组可重用的工作线程,从而避免频繁地创建和销毁线程带来的性能开销。线程池在Java中主要通过`java.util.concurrent`包中的`ExecutorService`接口及其...

    JAVA使用线程池查询大批量数据

    在Java开发中,处理大批量数据时,合理利用线程池可以显著提高程序的执行效率和资源利用率。本文将深入探讨如何在Java中使用线程池来查询大量数据,以及这样做的好处和实现方法。 首先,理解线程池的概念至关重要。...

    java 线程池常用方法

    Java线程池是Java并发编程中的重要组成部分,它在Java 5及后续版本中引入,大大简化了线程管理和资源调度。线程池通过`Executor`接口和`ExecutorService`接口提供了一套强大的机制,允许开发者高效地创建、管理和...

    50879510A6_Java线程池_funbde_

    - `shutdownNow()`: 尝试停止所有正在执行的任务,并不再接收新任务。 - `isShutdown()`: 检查线程池是否已关闭。 - `isTerminated()`: 检查线程池是否所有任务都已经完成。 `funbde`可能是指作者的名字或者是某个...

    Java线程池.docx

    // 关闭线程池,此时不再接受新任务,但仍会等待原有的任务执行完成,如果想要立即关闭,则可以使用 shutdownNow() executorService.shutdown(); } } ``` 在上面的示例代码中,我们首先创建了一个固定线程数量的...

    Java线程池介绍Java开发Java经验技巧共8页.pd

    Java线程池是Java并发编程中的重要组成部分,它在多线程编程中扮演着至关重要的角色,有效地管理和调度线程资源,提高了程序的性能和稳定性。本文将深入探讨Java线程池的概念、工作原理以及如何在实际开发中运用。 ...

    Java 线程池_动力节点Java学院整理

    Java线程池是一种高效管理线程资源的工具,它的出现是为了优化系统性能,尤其是在需要频繁创建和销毁线程的情况下。由于操作系统创建新线程需要进行内存分配、上下文切换等操作,这涉及到一定的开销。因此,使用...

    JAVA经典线程池源码

    Java线程池是Java并发编程中的重要组成部分,它在多线程编程中扮演着至关重要的角色,有效地管理和调度线程资源,提高了程序的性能和稳定性。本资源包含了一个经典的Java线程池实现,适用于大型项目,能帮助开发者...

    聊聊并发(3)Java线程池的分析和使用Java开发Jav

    3. **及时关闭线程池**:当不再使用线程池时,需要调用`shutdown`或`shutdownNow`方法,防止资源泄露。 4. **异常处理**:正确处理线程中的异常,避免因个别线程异常导致整个线程池停止运行。 在Java开发中,熟练...

    java 线程池 学习代码

    此外,`ThreadPoolExecutor`还提供了调整线程池参数的方法,如`setCorePoolSize(int)`、`setMaximumPoolSize(int)`等,以及关闭线程池的`shutdown()`和`shutdownNow()`方法。 在实际开发中,Java提供了一些预定义的...

    JAVA线程池的分析和使用

    JAVA线程池是一种高效管理线程的技术,它允许开发者预设线程数量,避免无限制地创建和销毁线程带来的开销。线程池通过控制并发级别,优化系统资源使用,提升系统的稳定性和响应速度。 1. **线程池的优势** - **...

    java线程池

    根据不同的应用场景和需求,Java线程池主要分为以下三种类型: ##### 1. `newFixedThreadPool` - **定义**:`newFixedThreadPool`是通过`Executors`工具类提供的一个工厂方法,用于创建固定大小的线程池。 - **...

    Android java 线程池

    3. **关闭线程池**:当不再需要线程池时,应调用`shutdown()`或`shutdownNow()`方法,确保资源被释放: ```java executor.shutdown(); ``` 4. **自定义线程池**:为了满足特定需求,可以创建自定义的线程池。...

    java线程池常用方法.docx

    ### Java线程池常用方法详解 #### 一、引言 自Java 5引入并发包`java.util.concurrent`以来,线程的管理与控制变得更为高效与便捷。在这个包中,`Executor`框架成为了线程管理和调度的核心。通过`Executor`,我们...

    Java/Android线程池演示Demo

    在Android和Java应用开发中,线程池是一种重要的并发编程工具,它可以帮助我们高效地管理后台任务,提高系统的响应速度和资源利用率。本Demo主要展示了如何在Java或Android环境中使用线程池,以下是对相关知识点的...

Global site tag (gtag.js) - Google Analytics