Как использовать ExecutorService параллельного программирования Java? - PullRequest
2 голосов
/ 25 февраля 2011

Я использую приведенный ниже код для загрузки изображений на удаленный сервер. Когда я использую ниже, он загружает все изображения одновременно на удаленный сервер.

List<Future<String>> futureList = new ArrayList<Future<String>>();
ExecutorService execService = Executors.newFixedThreadPool(Images.size());
for (IImage image : Images) { 
  try {
    //execService.execute(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
    singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
    //Log.d("","singleFuture -------"+singleFuture.get());
    futureList.add(singleFuture);
    Log.d("","futureList Size:"+futureList.size());
  } catch(Exception e){
    execService.shutdown();
  }

Всякий раз, когда я использовал ниже код

   singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
//Log.d("","singleFuture -------"+singleFuture.get());
    futureList.add(singleFuture);

добавляет все будущие объекты в список будущих объектов, сразу же возвращаясь из работоспособного состояния (не дожидаясь запуска в рабочем состоянии до завершения загрузки всех изображений (идет загрузка в фоновом режиме)

Но всякий раз, когда я комментирую нижнюю строку кода выше, после успешного завершениязагрузка каждого изображения, которое он возвращает из запускаемого файла.

singleFuture = execService.submit(lServerRequest.new uploadImages(image.getDataPath(),image.getDisplayName()));
Log.d("","singleFuture -------"+singleFuture.get());
futureList.add(singleFuture);

есть ли что-то не так в моем коде и нормально ли подключаться к удаленному серверу чаще, или какая-либо нагрузка на сервер? Как загрузить изображения?с помощью параллельного программирования Java? Пожалуйста, дайте нам руководство?

Имеют ли функции submit() и execute() одинаковый эффект?

Ответы [ 2 ]

3 голосов
/ 25 февраля 2011

Когда вы звоните singleFuture.get(), вы ожидаете завершения операции. Таким образом, цикл не будет продолжать выполнение следующего оператора, пока этот оператор не вернет результат.

Вам необходимо отправить свои задачи в первом цикле, а после этого другой цикл должен перебрать результаты future.get() в вашем списке, чтобы сделать его асинхронным

Из ответа @ andersoj;

Размер пула должен быть связан с ядром вашего процессора. Не количество изображений у вас на руках. Скажем, если у вас 2-ядерный процессор, коэффициент 5 (просто мое предположение о коэффициенте) для загрузки изображения во время.

POOL_SIZE = NUM_OF_CPU_CORE * coeffiecient;

2 голосов
/ 25 февраля 2011

submit() добавляет задачу в очередь и возвращает Future.execute() не возвращает Future.Смотри также здесь .Различные заказы, которые вы наблюдаете, могут быть побочными эффектами дополнительного управления, которые происходят внутри submit() и, вероятно, не имеют значения.(Но см. Ответ @ fmucar ...)

Не совсем точно определен ваш вопрос ...

Нет смысла определять размер пула потоков в зависимости от количества изображений.Вы хотите загрузить - возможно, достаточно небольшого количества потоков, так как вы просто пытаетесь поддерживать некоторые потоки TCP.Одна нить на изображение, если список изображений большой, ничего не купит.

Если вы собираете Futures только для того, чтобы узнать, когда загрузка завершена, рассмотрите одно из следующих действий:

Отредактировано для добавления : Good catch, @fmucar, вызов .get() в строке регистратора вызывает последовательность, поэтому пул потоковэто пустая трата времени.

invokeAll () пример

Вот попытка привести пример invokeAll();не уверен, что он полностью соответствует вашему коду.

final int poolSize = ...;  // see fmucar's answer
final ExecutorService execService = Executors.newFixedThreadPool(poolSize);
final List<Callable<>> uploadTasks = new ArrayList<Callable<>>();

for (final IImage image : Images) { 
   // maybe I got this wrong?  Can't quite parse your code.
   Callable<String> uTask = new uploadImages(image.getDataPath(),image.getDisplayName());
   uploadTasks.add(uTask);
}
// this thread will block here until all the tasks complete
final List<Future<String>> futureList = execService.invokeAll();
// or you can toss the result entirely if the futures don't matter.    
...