android多线程之三:终止线程池的方法

要了解如何线程池终止线程池,先来了解下线程池的几个方法:
shutdown、awaitTermination、shutdownNow、isTerminated、isShutdown

shutdown

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

awaitTermination

awaitTermination(long timeout, TimeUnit unit)这个方法有两个参数,一个是timeout即超时时间,另一个是unit即时间单位,比如timeout = 1,unit = TimeUnit.MINUTES,表示一分钟。

这个方法会使线程等待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的条件。

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)方法校验时返回的是true,因此没有输出:线程池没有关闭。而在调用shutdownNow方法时,我们接受到了一个List,这里包含的是在工作队列中等待执行的任务,由于线程池长度为3,且执行的都是长任务,所以当提交了三个任务后线程池已经满了,剩下的两次提交只能在工作队列中等待,因此我们看到runnables的大小为2,结果如下:

2  
线程池已经关闭  

isTerminated

当调用shutdown()方法后,并且所有提交的任务完成后返回为true,
这个方法会校验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。

isShutdown

当调用shutdown()方法后返回为true。

终止线程池

shutdown() 方法在终止前允许执行以前提交的任务,而 shutdownNow() 方法阻止等待任务启动并试图停止当前正在执行的任务。

在终止时,执行程序没有任务在执行,也没有任务在等待执行,并且无法提交新任务。应该关闭未使用的 ExecutorService 以允许回收其资源。

下列方法分两个阶段关闭 ExecutorService。
第一阶段调用 shutdown 拒绝传入任务,然后调用 shutdownNow(如有必要)取消所有遗留的任务:

void shutdownAndAwaitTermination(ExecutorService pool) {  
  pool.shutdown(); // Disable new tasks from being submitted  
  try {  
    // Wait a while for existing tasks to terminate  
    if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {  
      pool.shutdownNow(); // Cancel currently executing tasks  
      // Wait a while for tasks to respond to being cancelled  
      if (!pool.awaitTermination(60, TimeUnit.SECONDS))  
          System.err.println("Pool did not terminate");  
    }  
  } catch (InterruptedException ie) {  
    // (Re-)Cancel if current thread also interrupted  
    pool.shutdownNow();  
    // Preserve interrupt status  
    Thread.currentThread().interrupt();  
  }  
}  

shutdown调用后,不可以再submit新的task,已经submit的将继续执行。
shutdownNow试图停止当前正执行的task,并返回尚未执行的task的list

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值