美文网首页
线程池shutwown()方法调用的合适时机

线程池shutwown()方法调用的合适时机

作者: 猫尾草 | 来源:发表于2019-09-25 20:56 被阅读0次

1. 明确一个问题,线程池使用完需要调用shutdown关闭

  参考: https://www.jianshu.com/p/6e3f593c2616

2. 不合适的shutdown引发了问题

2.1 背景

  某存储项目,给客户提供sdk,其中提供了一个视频上传方法MultiPartOperatorClient,可以将本地视频上传到ceph的对象存储中去。
  MultiPartOperatorClient的构造函数同时初始化了VideoClient(用来与存储中台通信)和UrlUploader(根据存储中台生成的url将视频上传到ceph)。ceph的对象存储使用的是Amazon S3兼容方法,因为视频都比较大,使用分片上传,将视频切割为5M的片段,上传之后再合并。分片上传使用了线程池,即UrlUploader里面有线程池,当视频片段都上传完成,会调用线程池的shutdown方法。
代码示例:

/**
 * MultiPartOperationClient是提供给客户使用的视频上传方法,屏蔽了分片上传和中台通信等过程
 */
public class MultiPartOperationClient {

  private final UrlUploader urlUploader;
    private final VideoClient videoClient;

  public MultiPartOperatorClient() {
        this.videoClient = new VideoClient(accessKey, secretKey);
        this.urlUploader = new UrlUploader();
    }

  ...
}

/**
 * VideoClient负责与中台通信,根据用户信息获取视频上传地址等
 */
public class VideoClient {
  ...
}

/**
 * VideoClient负责与中台通信,根据用户信息获取视频上传地址等
 */
public class UrlUploader {
  ExecutorService executeService = new ThreadPoolExecutor(线程池的参数省略);

  public void multiPartupload() {
    while() {
      ...
      Future<String> result = this.executeService.submit(() -> 上传视频片段的方法);
      ...
    }
    this.executeService.shutdown();
  }
  ...
}

2.2 产生了一个问题

  在使用sdk的过程中,如果初始化了一个MultiPartOperationClient后,理应可以使用这个MultiPartOperationClient不停地上传视频,甚至多线程调用MultiPartOperationClient同时上传多个视频。
  但是MultiPartOperationClient和UrlUploader是两个同事分别写的。UrlUploader的作者为了保证自己的代码内存不泄露,在UrlUploader.multiPartupload()方法最后调用了shutdown()方法关闭了线程池,即当前视频的所有片段都上传完成后关闭线程池。
  MultiPartOperationClient的作者没注意到这个问题,将UrlUploader的初始化放在了构造函数里,这样MultiPartOperationClient如果想上传多个视频,每次上传视频使用的都是同一个UrlUploader,但是第一个视频上传完成后UrlUploader的线程池已经关闭,无法再接收视频片段上传任务,这时就会报错:java.util.concurrent.RejectedExecutionException
  java.util.concurrent.RejectedExecutionException的意思是线程数超过了当前线程池容量,有两种可能:

  • 提交太多线程超过了线程池容量
  • 线程池被关闭容量为0自然提交任何线程都是超过了容量。

2.3 解决办法

  • UrlUploader的初始化不要放在MultiPartOperationClient的构造函数中,每次调用时构造(这样有点浪费资源?)。
  • UrlUploader作为MultiPartOperationClient的私有方法,在MultiPartOperationClient的finalize()方法中执行线程池的shutdown()方法。

相关文章

  • Java线程池拒绝策略

    【Java线程池拒绝任务策略】创建线程池可以指定拒绝策略如下: 一 拒绝时机1) 调用线程池的shutdown函数...

  • spring boot线程池使用

    线程池配置 线程池方法定义 单测调用

  • shutdown、shutdownNow方法的理解

    shutdown() 1、当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池...

  • Spring Boot 配置异步Async方法

    注解启动类 添加线程池配置 标注异步方法-不带返回值 标注异步方法-不带返回值 线程池的调用过程 核心线程池未满时...

  • shutdown、shutdownNow

    shutdown()1、当线程池调用该方法时,线程池的状态则立刻变成SHUTDOWN状态。此时,则不能再往线程池中...

  • java基础专题:2. java四种线程池的区别

    java有四种线程池 这四种线程池,本质上,都是调用ThreadPoolExecutor方法进行构造的。那么他们的...

  • Java 钩子程序

    简介 触发的时机有: 当所有的非deamon线程(守护线程)结束, 或者调用了Systrem.exit()方法 而...

  • JAVA 线程池Executors

    Executors类提供的四种创建线程池方法 调用的都是ThreadPoolExecutor构造方法 1. Fix...

  • 线程池Woker类讲解

    通常我们利用线程池执行任务时,一般会调用execute()方法来进行任务的提交。 然后如果线程池不是将任务放在工作...

  • NSTimer使用遇到的问题

    1 如果能找到合适的时机,无论timer是weak修饰还是strong修饰,主动调用 invalidate方法,那...

网友评论

      本文标题:线程池shutwown()方法调用的合适时机

      本文链接:https://www.haomeiwen.com/subject/wsbjuctx.html