温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Java如何使用ExecutorService停止线程服务的方法

发布时间:2021-03-10 15:44:52 来源:亿速云 阅读:534 作者:TREX 栏目:编程语言

这篇文章主要介绍“Java如何使用ExecutorService停止线程服务的方法”,在日常操作中,相信很多人在Java如何使用ExecutorService停止线程服务的方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java如何使用ExecutorService停止线程服务的方法”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Java可以用来干什么

Java主要应用于:1. web开发;2. Android开发;3. 客户端开发;4. 网页开发;5. 企业级应用开发;6. Java大数据开发;7.游戏开发等。


使用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),因为之前的判断不是原子操作,则可能会产生误报。

到此,关于“Java如何使用ExecutorService停止线程服务的方法”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI