单例执行程序Java

时间:2018-06-13 09:27:47

标签: java threadpool executorservice

您好我正在尝试为二进制文件下载创建执行程序,我有大约100-200个文件要下载并存储在磁盘中。

这是我的DownloadExecutor.java

public final class DownloadExecutor {

  private static DownloadExecutor executor;

  private ExecutorService executorService;

  private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
      return new Thread(r, "DownloadExecutor #" + mCount.getAndIncrement());
    }
  };

  public static DownloadExecutor getInstance() {
    if (executor == null) {
      synchronized (DownloadExecutor.class) {
        executor = new DownloadExecutor();
      }
    }
    return executor;
  }

  private DownloadExecutor() {
    final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);
    final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    // We want at least 2 threads and at most 4 threads in the core pool,
    // preferring to have 1 less than the CPU count to avoid saturating
    // the CPU with background work
    final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
    final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    final int KEEP_ALIVE_SECONDS = 2;
    StringBuilder stringBuilder = new StringBuilder();
    stringBuilder.append("CPU: " + CPU_COUNT);
    stringBuilder.append(",CORE POOL: " + CORE_POOL_SIZE);
    stringBuilder.append(",MAX POOL: " + MAXIMUM_POOL_SIZE);
    System.out.println("Executor log: " + stringBuilder.toString());
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
        CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS,
        sPoolWorkQueue, sThreadFactory);
    threadPoolExecutor.allowCoreThreadTimeOut(true);
    executorService = threadPoolExecutor;
  }

  public void execute(Callable<?> callable) {
    System.out.println("Adding");
    executorService.submit(callable);
  }
}

我使用以下代码提交任务 DownloadExecutor.getInstance().execute(someCallable);

最初,当我触发所有下载成功时,但是当我下次触发它时会抛出java.util.concurrent.RejectedExecutionException

注意我不想在此使用shutDown(),这个愿望是否可以省略shutDown。当您尝试在已终止服务上提交任务时,我意识到java.util.concurrent.RejectedExecutionException

致电代码

for (int i = 0; i < totalVideos; i++) {
      try {
        DownloadExecutor.getInstance().execute(new YoutubeFilewriter(downloadRepository,
            videoDao, listResource.data.get(i), parentPath, YoutubeVideoDownloader.this));
      } catch (IOException e) {
        e.printStackTrace();
        ++failedVideos;
      }
    }

想象一下,每次按下按钮都会触发此代码。

1 个答案:

答案 0 :(得分:0)

你的问题是

final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128);

如果所有执行程序线程都忙且队列已满,则抛出RejectedExecutionException。

增加池大小或使用无界队列。

顺便说一下。不要对你的单身人士使用双重检查锁定(https://wiki.sei.cmu.edu/confluence/display/java/LCK10-J.+Use+a+correct+form+of+the+double-checked+locking+idiom)。