Java使用ExecutorService来停止线程服务

使用ExecutorService来停止线程服务

之前的文章中我们提到了ExecutorService可以使用shutdown和shutdownNow来关闭。

这两种关闭的区别在于各自的安全性和响应性。shutdownNow强行关闭速度更快,但是风险也更大,因为任务可能正在执行的过程中被结束了。而shutdown正常关闭虽然速度比较慢,但是却更安全,因为它一直等到队列中的所有任务都执行完毕之后才关闭。

使用shutdown

我们先看一个使用shutdown的例子:

  public void useShutdown() throws InterruptedException {
    ExecutorService executor = Executors.newFixedThreadPool(10);

    Runnable runnableTask = () -> {
      try {
        TimeUnit.MILLISECONDS.sleep(300);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    };

    executor.submit(runnableTask);
    executor.shutdown();
    executor.awaitTermination(800, TimeUnit.MILLISECONDS);
  }

awaitTermination将会阻塞直到所有正在执行的任务完成,或者达到指定的timeout时间。

使用shutdownNow

当通过shutdownNow来强行关闭ExecutorService是, 它会尝试取消正在执行的任务,并返回所有已经提交但是还没有开始的任务。从而可以将这些任务保存起来,以便以后进行处理。

但是这样我们只知道了还没有开始执行的任务,对于那些已经开始执行但是没有执行完毕却被取消的任务我们无法获取。

我们看下如何获得开始执行但是还没有执行完毕的任务:

public class TrackingExecutor extends AbstractExecutorService {
  private final ExecutorService executorService;
  private final Set<Runnable> taskCancelledAtShutdown= Collections.synchronizedSet(new HashSet<Runnable>());

  public TrackingExecutor(ExecutorService executorService){
     this.executorService=executorService;
  }
  @Override
  public void shutdown() {
    executorService.shutdown();
  }

  @Override
  public List<Runnable> shutdownNow() {
    return executorService.shutdownNow();
  }

  @Override
  public boolean isShutdown() {
    return executorService.isShutdown();
  }

  @Override
  public boolean isTerminated() {
    return executorService.isTerminated();
  }

  @Override
  public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
    return executorService.awaitTermination(timeout,unit);
  }

  @Override
  public void execute(Runnable command) {
    executorService.execute(() -> {
      try {
        command.run();
      }finally {
        if(isShutdown() && Thread.currentThread().isInterrupted()){
          taskCancelledAtShutdown.add(command);
        }
      }
    });
  }

  public List<Runnable> getCancelledTask(){
    if(! executorService.isTerminated()){
      throw new IllegalStateException("executorService is not terminated");
    }
    return new ArrayList<>(taskCancelledAtShutdown);
  }
}

上面的例子中我们构建了一个新的ExecutorService,他传入一个ExecutorService,并对其进行封装。

我们重写了execute方法,在执行完毕判断该任务是否被中断,如果被中断则将其添加到CancelledTask列表中。

并提供一个getCancelledTask方法来返回未执行完毕的任务。

我们看下怎么使用:

  public void useShutdownNow() throws InterruptedException {
    TrackingExecutor trackingExecutor=new TrackingExecutor(Executors.newCachedThreadPool());

    Runnable runnableTask = () -> {
      try {
        TimeUnit.MILLISECONDS.sleep(300);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    };

    trackingExecutor.submit(runnableTask);
    List<Runnable> notrunList=trackingExecutor.shutdownNow();
    if(trackingExecutor.awaitTermination(800, TimeUnit.SECONDS)){
      List<Runnable> runButCancelledList= trackingExecutor.getCancelledTask();
    }
  }

trackingExecutor.shutdownNow()返回的是未执行的任务。而trackingExecutor.getCancelledTask()返回的是被取消的任务。

上面的任务其实还有一个缺点,因为我们在存储被取消的任务列表的额时候taskCancelledAtShutdown.add(command),因为之前的判断不是原子操作,则可能会产生误报。

本文的例子请参考https://github.com/ddean2009/learn-java-concurrency/tree/master/ExecutorServiceShutdown

到此这篇关于Java使用ExecutorService来停止线程服务的文章就介绍到这了,更多相关Java ExecutorService停止线程内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

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

    Java 线程池ExecutorService 1.线程池 1.1什么情况下使用线程池 单个任务处理的时间比较短. 将需处理的任务的数量大. 1.2使用线程池的好处 减少在创建和销毁线程上所花的时间以及系统资源的开销. 如果不使用线程池,有可能造成系统创建大量线程而导致消耗系统内存以及"过度切换"; 2.ExecutorService和Executors 2.1简介 ExecutorService是一个接口,继承了Executor, public interface ExecutorS

  • Java ExecutorService四种线程池使用详解

    1.引言 合理利用线程池能够带来三个好处.第一:降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗.第二:提高响应速度.当任务到达时,任务可以不需要的等到线程创建就能立即执行.第三:提高线程的可管理性.线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控.但是要做到合理的利用线程池,必须对其原理了如指掌. 2.线程池使用 Executors提供的四种线程 1.newCachedThreadPool创建一个可缓存线程池

  • 理解java多线程中ExecutorService使用

    java.util.concurrent包里提供了关于多线程操作的类,平常用的比较多的是ExecutorService及其实现类(如ThreadPoolExecutor等),Executor,Executors,Future,Callable等 1. ExecutorService(继承自Executor)接口:提供了一些异步的多线程操作方法,如execute(), submit(), shutdown(), shutdownNow()等 2. Executor接口:执行提交的任务(线程),只有

  • 详解Java利用ExecutorService实现同步执行大量线程

    自从java1.5以后,官网就推出了Executor这样一个类,这个类,可以维护我们的大量线程在操作临界资源时的稳定性. 先上一段代码吧: TestRunnable.java public class TestRunnable implements Runnable { private String name; public TestRunnable(String name) { this.name = name; } @Override public void run() { while (t

  • 在spring boot中使用java线程池ExecutorService的讲解

    1. 认识java线程池 1.1 在什么情况下使用线程池? 1.单个任务处理的时间比较短 2.需处理的任务的数量大 1.2 使用线程池的好处: 1.减少在创建和销毁线程上所花的时间以及系统资源的开销 2.如不使用线程池,有可能造成系统创建大量线程而导致消耗完系统内存 1.3 线程池包括以下四个基本组成部分: 1.线程池管理器(ThreadPool):用于创建并管理线程池,包括 创建线程池,销毁线程池,添加新任务: 2.工作线程(PoolWorker):线程池中线程,在没有任务时处于等待状态,可以

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

    复制代码 代码如下: package com.yao; import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.ScheduledFuture;import java.util.concurrent.TimeUnit; /** * 以下是一个带方法的类,它设置了 ScheduledExecutorService ,2

  • Java使用ExecutorService来停止线程服务

    使用ExecutorService来停止线程服务 之前的文章中我们提到了ExecutorService可以使用shutdown和shutdownNow来关闭. 这两种关闭的区别在于各自的安全性和响应性.shutdownNow强行关闭速度更快,但是风险也更大,因为任务可能正在执行的过程中被结束了.而shutdown正常关闭虽然速度比较慢,但是却更安全,因为它一直等到队列中的所有任务都执行完毕之后才关闭. 使用shutdown 我们先看一个使用shutdown的例子: public void use

  • Java 停止线程需要注意的地方

    Java中停止线程的原则是什么? 在 Java 中, 最好的停止线程的方式是使用中断 interrupt, 但是这仅仅是会通知到被终止的线程 "你该停止运行了", 被终止的线程自身拥有决定权 (决定是否.以及何时停止), 这依赖于请求停止方和被停止方都遵守一种约定好的编码规范. 任务和线程的启动很容易. 在大多数时候, 我们都会让它们运行直到结束, 或者让它们自行停止.然而, 有时候我们希望提前结束任务或线程, 或许是因为用户取消了操作,或者服务需要被快速关闭, 或者是运行超时或出错了

  • 详解Java停止线程的四种方法

    一.线程停止基础知识 interrupted(): 测试当前线程是否已经中断.该方法为静态方法,调用后会返回boolean值.不过调用之后会改变线程的状态,如果是中断状态调用的,调用之后会清除线程的中断状态. isInterrupted(): 测试线程是否已经中断.该方法由对象调用 interrupt(): 标记线程为中断状态,不过不会中断正在运行的线程. stop(): 暴力停止线程.已弃用. 二.停止线程方法1:异常法停止 线程调用interrupt()方法后,在线程的run方法中判断当前对

  • Java通过在主循环中判断Boolean来停止线程的方法示例

    本文实例讲述了Java通过在主循环中判断Boolean来停止线程的方法.分享给大家供大家参考,具体如下: package Threads; /** * Created by Frank */ public class StopBoolean extends Thread { // 确保变化对其它线程可见(主要是主线程要可见) protected volatile boolean done = false; public void run() { while (!done) { System.ou

  • java多线程之停止线程的方法实例代码详解

    和线程停止相关的三个方法 /* 中断线程.如果线程被wait(),join(),sleep()等方法阻塞,调用interrupt()会清除线程中断状态,并收到InterruptedException异常.另外interrupt();对于isAlive()返回false的线程不起作用. */ public void interrupt(); /* 静态方法,判断线程中断状态,并且会清除线程的中断状态.所以连续多次调用该方法,第二次之后必定返回false.另外,isAlive()用于判断线程是否处于

  • 面试题:Java中如何停止线程的方法

    如何停止线程是Java并发面试中的常见问题,本篇文章将从答题思路到答题细节给出一些参考. 答题思路: 停止线程的正确方式是使用中断 想停止线程需要停止方,被停止方,被停止方的子方法相互配合 扩展到常见的错误停止线程方法:已被废弃的stop/suspend,无法唤醒阻塞线程的volatile 1. 正确方式是中断 其实从逻辑上也很好理解的,一个线程正在运行,如何让他停止? A. 从外部直接调用该线程的stop方法,直接把线程停下来. B. 从外部通过中断通知线程停止,然后切换到被停止的线程,该线程

  • Java停止线程的3种方法

    目录 1.自定义中断标识符 2.interrupt中断线程 3.stop停止线程 总结 在 Java 中停止线程的实现方法有以下 3 种: 自定义中断标识符,停止线程. 使用线程中断方法 interrupt 停止线程. 使用 stop 停止线程. 其中 stop 方法为 @Deprecated 修饰的过期方法,也就是不推荐使用的过期方法,因为 stop 方法会直接停止线程,这样就没有给线程足够的时间来处理停止前的保存工作,就会造成数据不完整的问题,因此不建议使用.而自定义中断标识也有一些问题,所

  • java通过共享变量结束run停止线程的方法示例

    stop()方法已经被弃用,原因是不太安全.API文档中给出了具体的详细解释.通过interrupted()方法打断线程.不推荐.通过共享变量结束run()方法,进而停止线程.如实例 复制代码 代码如下: public class ThreadInterrupt {    public static void main(String []args){        Runner run = new Runner();        run.start();        try {       

  • 浅谈java常用的几种线程池比较

    1. 为什么使用线程池 诸如 Web 服务器.数据库服务器.文件服务器或邮件服务器之类的许多服务器应用程序都面向处理来自某些远程来源的大量短小的任务.请求以某种方式到达服务器,这种方式可能是通过网络协议(例如 HTTP.FTP 或 POP).通过 JMS 队列或者可能通过轮询数据库.不管请求如何到达,服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的. 构建服务器应用程序的一个简单模型是:每当一个请求到达就创建一个新线程,然后在新线程中为请求服务.实际上对于原型开发这

随机推荐