如何使用java并发编程的ExecutorService?

时间:2011-02-25 10:09:24

标签: java concurrent-programming

我使用下面的代码在远程服务器上上传图像。当我在下面使用时,它会在远程服务器上并行上传所有图像。

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

将所有未来的对象添加到futurelist中,立即从runnable返回(不等待runnable直到完成所有图像的上传(后台上传处理正在进行)

但是,无论何时我在上面的代码中取消注释,在成功上传每个图像后,它都会从runnable返回。

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

我的代码是否有任何问题,是否可以一次更多地连接远程服务器或服务器上有任何负载?如何使用并发编程java上传图像?请给我们指导?

submit()execute()功能是否具有相同的效果?

2 个答案:

答案 0 :(得分:3)

当您致电singleFuture.get()时,您正在等待操作完成。因此循环不会继续执行下一个语句,直到返回结果。

您需要在第一个循环中提交您的任务,之后,另一个循环应该遍历列表中的结果future.get()以使其异步

来自@ andersoj的回答;

池大小应与CPU核心相关。不是您手中的图像数量。假设您有2个核心CPU,系数为5(只是我的系数猜测),可以用于图像上传。

POOL_SIZE = NUM​​_OF_CPU_CORE * coeffiecient;

答案 1 :(得分:2)

submit()向队列添加任务并返回Futureexecute()不会返回Future。另见here。您观察到的不同排序可能会发生在submit()内发生的额外管理的副作用,并且可能无关紧要。 (但请参阅@ fmucar的答案......)

不确定您的问题是什么......

根据您要上传的图像数量调整线程池的大小没有意义 - 可能只有少量线程就足够了,因为您只是想保留一些TCP流。每张图片一个帖子,如果图片列表很大,就不会给你买任何东西。

如果您仅在知道上传完成时收集Futures,请考虑以下其中一项:

编辑添加:好捕获,@ 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.