Постоянные переменные в ExecutorService (Java) - PullRequest
5 голосов
/ 20 октября 2011

Я создал пул из 4 рабочих потоков для обработки некоторых файлов.В тесте их около 200.Версия пула потоков уже примерно в 3 раза быстрее, чем последовательно, но есть возможности для улучшения.

Самое большое узкое место (игнорирование дискового ввода / вывода) - это необходимость создания нового объекта MessageDigest.В однопоточной версии у меня было только 1. В этой версии у меня 200.

Мне было интересно, возможно ли иметь локальную переменную для потока в рабочем пуле?Таким образом (при условии отсутствия потоков) будет только четыре экземпляра объекта MessageDigest, а не 200 ...

Каждая задача требует дайджеста, поэтому я не уверен, есть ли лучший способ сделать это...

ОБНОВЛЕНИЕ

Я пытался использовать объект ThreadLocal, но где мне его создать?Если я создам его в самой задаче, думаю, он выйдет из контекста, когда задача будет завершена.Каждый раз, когда создается новый экземпляр.Код, который у меня есть:

    ThreadLocal<GenerateSHA1> tl = new ThreadLocal<GenerateSHA1>();

    hashMaker = tl.get();
    if(hashMaker == null){
        hashMaker = new GenerateSHA1();
        tl.set(hashMaker);
    }

Это делается из конструктора задачи.

ОБНОВЛЕНИЕ

Хорошо, это делает статический вид работ в том, что объектне теряется - но теперь выделена другая проблема.Рабочие «задачи» создаются в главном потоке, а затем добавляются в ExecutorService с помощью invokeAll ().

Есть идеи как обойти это?

Ответы [ 3 ]

3 голосов
/ 20 октября 2011

Расширьте ThreadLocal для своего класса и переопределите метод initialValue(). По умолчанию возвращается ноль.

private static class ThreadLocalGenerateSHA1 extends
  ThreadLocal<GenerateSHA1> {

  @Override
  protected GenerateSHA1 initialValue() {
    return new GenerateSHA1();
  }

}

private static final ThreadLocalGenerateSHA1 generateSHA1 = new ThreadLocalGenerateSHA1();

...

В задачах просто вызовите get() метод generateSHA1. Вам не нужно звонить set().

0 голосов
/ 20 октября 2011

Вы можете использовать пул объектов для ваших объектов дайджеста сообщений.И установите размер пула на 4 в вашем случае.

apache commons обеспечивает отличный пул api: http://commons.apache.org/pool/

0 голосов
/ 20 октября 2011

Вы можете воспользоваться помощью beforeExecute и afterExecute методов ThreadPoolExecutor, расширив его.В расширенном классе создайте 4 объекта MessageDigest и назначьте их для каждой задачи в beforeExecute (...) циклическим образом.

private static final Executor executor = new MyThreadPoolExecutor(10, 10, 50000L,   TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(100));

EDIT

Я чувствую пул объектоввариант, упомянутый Рави Бхаттом как простая и элегантная идея.Создайте пул и позвольте задаче запросить MessageDigest из пула.

...