Синглтон исполнитель Java - PullRequest
0 голосов
/ 13 июня 2018

Привет, я пытаюсь создать исполнителя для загрузки двоичных файлов, у меня есть около 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 голосов
/ 13 июня 2018

Ваша проблема

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

Если все потоки исполнителя заняты, а ваша очередь заполнена, генерируется исключение RejectedExecutionException.

Либо увеличьте размер пула, либо используйте неограниченную очередь.

Btw.не используйте двойную проверку блокировки для вашего синглтона (https://wiki.sei.cmu.edu/confluence/display/java/LCK10-J.+Use+a+correct+form+of+the+double-checked+locking+idiom).

...