`
victorzhzh
  • 浏览: 203008 次
  • 来自: ...
社区版块
存档分类
最新评论

ExecutorService生命周期

阅读更多

ExecutorService接口继承了Executor接口,定义了一些生命周期的方法

public interface ExecutorService extends Executor {
void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException;
}

本文,我们逐一分析里面的每个方法。

 

首先,我们需要创建一个任务代码,这段任务代码主要是随机生成含有10个字符的字符串

/**
 * 随机生成10个字符的字符串
 * @author dream-victor
 *
 */
public class Task1 implements Callable<String> {

	@Override
	public String call() throws Exception {
		String base = "abcdefghijklmnopqrstuvwxyz0123456789";
		Random random = new Random();
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < 10; i++) {
			int number = random.nextInt(base.length());
			sb.append(base.charAt(number));
		}
		return sb.toString();
	}

}

 然后,我们还需要一个长任务,这里我们默认是沉睡10秒,

/**
 * 长时间任务
 * 
 * @author dream-victor
 * 
 */
public class LongTask implements Callable<String> {

	@Override
	public String call() throws Exception {
		TimeUnit.SECONDS.sleep(10);
		return "success";
	}

}

OK,所有前期准备完毕,下面我们就来分析一下ExecutorService接口中和生命周期有关的这些方法:

 

1、shutdown方法:这个方法会平滑地关闭ExecutorService,当我们调用这个方法时,ExecutorService停止接受任何新的任务且等待已经提交的任务执行完成(已经提交的任务会分两类:一类是已经在执行的,另一类是还没有开始执行的),当所有已经提交的任务执行完毕后将会关闭ExecutorService。这里我们先不举例在下面举例。

 

2、awaitTermination方法:这个方法有两个参数,一个是timeout即超时时间,另一个是unit即时间单位。这个方法会使线程等待timeout时长,当超过timeout时间后,会监测ExecutorService是否已经关闭,若关闭则返回true,否则返回false。一般情况下会和shutdown方法组合使用。例如:

ExecutorService service = Executors.newFixedThreadPool(4);
service.submit(new Task1());
service.submit(new Task1());
service.submit(new LongTask());
service.submit(new Task1());

service.shutdown();

while (!service.awaitTermination(1, TimeUnit.SECONDS)) {
	System.out.println("线程池没有关闭");
}
System.out.println("线程池已经关闭");

 这段代码中,我们在第三次提交了一个长任务,这个任务将执行10秒沉睡,紧跟着执行了一次shutdown()方法,假设:这时ExecutorService被立即关闭,下面调用service.awaitTermination(1, TimeUnit.SECONDS)方法时应该返回true,程序执行结果应该只会打印出:“线程池已经关闭”。但是,真实的运行结果如下:

线程池没有关闭
线程池没有关闭
线程池没有关闭
线程池没有关闭
线程池没有关闭
线程池没有关闭
线程池没有关闭
线程池没有关闭
线程池没有关闭
线程池已经关闭

 这说明我们假设错误,service.awaitTermination(1, TimeUnit.SECONDS)每隔一秒监测一次ExecutorService的关闭情况,而长任务正好需要执行10秒,因此会在前9秒监测时ExecutorService为未关闭状态,而在第10秒时已经关闭,因此第10秒时输出:线程池已经关闭。这也验证了shutdown方法关闭ExecutorService的条件。

 

3、shutdownNow方法:这个方法会强制关闭ExecutorService,它将取消所有运行中的任务和在工作队列中等待的任务,这个方法返回一个List列表,列表中返回的是等待在工作队列中的任务。例如:

		ExecutorService service = Executors.newFixedThreadPool(3);
		service.submit(new LongTask());
		service.submit(new LongTask());
		service.submit(new LongTask());
		service.submit(new LongTask());
		service.submit(new LongTask());
		
		List<Runnable> runnables = service.shutdownNow();
		System.out.println(runnables.size());

		while (!service.awaitTermination(1, TimeUnit.MILLISECONDS)) {
			System.out.println("线程池没有关闭");
		}
		System.out.println("线程池已经关闭");

 这段代码中,我们限制了线程池的长度是3,提交了5个任务,这样将有两个任务在工作队列中等待,当我们执行shutdownNow方法时,ExecutorService被立刻关闭,所以在service.awaitTermination(1, TimeUnit.MILLISECONDS)方法校验时返回的是false,因此没有输出:线程池没有关闭。而在调用shutdownNow方法时,我们接受到了一个List,这里包含的是在工作队列中等待执行的任务,由于线程池长度为3,且执行的都是长任务,所以当提交了三个任务后线程池已经满了,剩下的两次提交只能在工作队列中等待,因此我们看到runnables的大小为2,结果如下:

2
线程池已经关闭
 

4、isTerminated方法:这个方法会校验ExecutorService当前的状态是否为“TERMINATED”即关闭状态,当为“TERMINATED”时返回true否则返回false。例如:

		ExecutorService service = Executors.newFixedThreadPool(3);
		service.submit(new Task1());
		service.submit(new Task1());
		service.submit(new LongTask());

		service.shutdown();
		System.out.println(System.currentTimeMillis());
		while (!service.isTerminated()) {
		}
		System.out.println(System.currentTimeMillis());

这段代码我们执行了两个正常的任务和一个长任务,然后调用了shutdown方法,我们知道调用shutdown方法并不会立即关闭ExecutorService,这时我们记录一下监测循环执行前的时间,在没有关闭前我们一直进入一个空循环中,直到 ExecutorService关闭后退出循环,这里我们知道长任务执行时间大约为10秒,我们看一下上述程序运行结果:

1303298818621
1303298828634
相差:10013毫秒,转换一下除以1000,得到相差大约10秒

这10秒正好是长任务执行的时间,因此在 ExecutorService正常关闭后isTerminated方法返回true。

 

5、isShutdown方法:这个方法在ExecutorService关闭后返回true,否则返回false。方法比较简单不再举例。

以上讨论是基于ThreadPoolExecutor的实现,不同的实现会有所不同需注意。

 

分享到:
评论
4 楼 120153216 2015-04-23  
3 楼 sun-wanx 2014-07-03  
这段代码中,我们限制了线程池的长度是3,提交了5个任务,这样将有两个任务在工作队列中等待,当我们执行shutdownNow方法时,ExecutorService被立刻关闭,所以在service.awaitTermination(1, TimeUnit.MILLISECONDS)方法校验时返回的是false,因此没有输出:线程池没有关闭。

下划线的应该有问题把,是不是返回true 才会跟打印结果匹配。
2 楼 aty 2014-05-28  
写的很好。借鉴哥们的思路,自己也尝试下,加什么对并发API的理解和使用
1 楼 zzb7728317 2014-05-14  
不错不错 学习了

相关推荐

    ExecutorService的execute和submit方法

    在Java多线程编程中,`ExecutorService`是线程池的核心接口,它提供了一种管理线程的方式,包括创建线程、调度线程执行以及控制线程的生命周期。`ExecutorService`通过`execute()`和`submit()`这两个方法来提交任务...

    ExecutorService.shutdown()应该是在线程执行完毕后,才会去关闭

    线程池的生命周期管理是非常重要的,不正确的关闭可能导致资源泄露或应用程序异常退出。在设计系统时,我们需要考虑到线程池的关闭时机,通常是在应用程序关闭或者不再需要服务时进行。 此外,了解`Future`接口也很...

    Java线程生命周期.zip

    Java线程生命周期是Java编程中的核心概念,它关乎程序的并发执行和性能优化。线程在Java中扮演着至关重要的角色,特别是在多任务处理和实时系统中。理解线程的生命周期有助于开发者更有效地管理和控制程序运行流程。...

    线程的生命周期.pdf

    Java线程的生命周期是编程中一个关键的概念,尤其是在多线程编程中。线程的生命周期主要包括以下几个阶段: 1. **创建**:线程的创建可以通过两种方式:直接实例化Thread类或者继承Thread类并重写run()方法。例如,...

    java ExecutorService使用方法详解

    线程的生命周期由`ExecutorService`内部管理,如果线程完成了它的任务,`ExecutorService`会决定是否回收这个线程。 6. **线程的生命周期** 在`JobThread`的`run()`方法中,线程会持续运行,直到主线程将其从`...

    java并发编程:Executor、Executors、ExecutorService.docx

    ExecutorService是Executor的子接口,提供了更丰富的功能,包括生命周期管理、任务调度以及返回Future对象的能力。ExecutorService允许我们优雅地关闭服务,例如通过调用`shutdown()`方法,它会停止接受新的任务并...

    Java 线程池ExecutorService详解及实例代码

    线程池的主要目的是为了优化线程的生命周期管理。在处理大量并发任务时,如果每个任务都单独创建线程,那么频繁的线程创建和销毁会带来很大的性能开销。线程池可以预先创建一定数量的线程,待有任务提交时直接复用,...

    java 线程的生命周期详解

    在实际编程中,我们还可以使用线程池来管理线程,比如`ExecutorService`,它可以帮助我们更好地控制线程的创建和销毁,减少线程生命周期的开销。此外,线程间的同步和通信机制,如`synchronized`关键字、`wait()`, `...

    java多线程并发executorservice(任务调度)类

    4. 可以控制线程池的生命周期,如通过 `shutdown` 方法优雅地关闭线程池。 了解这些知识点对于编写高效、可控的并发程序至关重要。在实际应用中,可以根据任务的特性选择合适的线程池配置,以达到最佳性能和资源...

    multithread:使用 Java8 ExecutorService 的简单多线程示例

    6. **线程池的生命周期**:ExecutorService 在创建后处于运行状态,当调用 `shutdown()` 后,它进入“关闭”状态,不再接受新的任务,但会继续执行已提交的任务。当所有任务执行完毕,或者 `shutdownNow()` 被调用并...

    java并发库学习笔记

    `ExecutorService`是`Executor`接口的一个扩展,它添加了生命周期管理的方法,包括启动、关闭和终止线程池。`ExecutorService`允许我们提交任务(Runnable或Callable)来执行,并且可以控制线程池的行为,如设置线程...

    线程的生命期设计

    1. **线程的生命周期** - **创建**:当应用程序通过调用特定的API(如Java中的`Thread`类或C++中的`std::thread`)来创建一个新线程时,线程就进入了创建状态。 - **就绪**:线程被创建后,如果没有其他阻塞因素,...

    Java/Android线程池演示Demo

    然而,对于大量或长生命周期的任务,直接使用`ExecutorService`和`ThreadPoolExecutor`会更合适,因为它能更好地控制线程的生命周期和并发级别。 六、线程池的关闭 在应用退出或不再需要线程池时,应调用`...

    Android经典源码全集

    7. **生命周期管理**:Activity、Fragment的生命周期是Android开发的基础,源码会展示如何在不同生命周期方法中进行合适的操作,以及如何使用ViewModel和Lifecycle库来处理复杂的生命周期问题。 8. **动画效果**:...

    08 服务与多线程1

    - 当Service不再需要时,调用`stopService()`或`stopSelf()`,Service的`onDestroy()`方法会被调用,标志着Service的生命周期结束。 2. **停止Service** - 使用`stopService(Intent)`或`stopSelf()`可以在Service...

    ThreadBestPrices

    在"ThreadBestPrices"中,可能会展示如何创建、启动和管理线程,以及如何利用`ExecutorService`进行线程池管理,以优化线程的生命周期和减少资源消耗。 其次,最佳实践通常包括同步控制,以避免数据竞争和死锁。...

    Android线程池ExcutorService

    `ExecutorService`是`java.util.concurrent`包下的接口,它提供了一种优雅的方式来管理和控制线程的生命周期,包括创建、执行和销毁线程。在Android应用中,正确地使用线程池可以显著提高应用程序的性能和响应性,...

    Java线程创建与管理:深入理解与实践指南

    本文将详细介绍Java中创建线程的不同方法,并探讨如何有效地管理线程的生命周期,以帮助读者更好地理解和应用Java多线程编程技术。 #### Java线程基础 在Java中,线程是程序中最小的可调度单元,它可以在程序中独立...

    设计滚动字演示线程状态及改变方法

    - **ExecutorService**:Java 5引入了`ExecutorService`,它可以管理和控制线程池,提高性能和资源利用率。 综上所述,设计滚动字演示线程状态及改变方法涉及到了Java GUI编程、多线程控制、线程状态管理、动画...

Global site tag (gtag.js) - Google Analytics