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

2019-09-25  本文已影响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的意思是线程数超过了当前线程池容量,有两种可能:

2.3 解决办法

上一篇 下一篇

猜你喜欢

热点阅读