java - Java 单例执行器

标签 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;
      }
    }

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

最佳答案

你的问题是

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 )。

关于java - Java 单例执行器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50833716/

相关文章:

java - 不幸的是,应用程序在 Android 中的 AVD 上停止了

java - 将java线程池中的线程设置为守护线程是否有任何问题

java - 在java中创建多个线程

java - java.lang.Thread.State : WAITING (parking) 90%线程解析

android - Future.get 阻塞了吗?

java Akka 。如何将参与者的行为与许多泛型相匹配

java - 如何使用 sikuli 和 selenium webdriver java 自动化 flash

java - 如何用java计算支持度的置信度

java - 使用执行器运行多个线程时如何立即捕获错误?

java - 在 Spring boot 中使用两个执行器运行并行作业