我使用下面的代码在远程服务器上上传图像。当我在下面使用时,它会在远程服务器上并行上传所有图像。
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()
功能是否具有相同的效果?
答案 0 :(得分:3)
当您致电singleFuture.get()
时,您正在等待操作完成。因此循环不会继续执行下一个语句,直到返回结果。
您需要在第一个循环中提交您的任务,之后,另一个循环应该遍历列表中的结果future.get()
以使其异步
来自@ andersoj的回答;
池大小应与CPU核心相关。不是您手中的图像数量。假设您有2个核心CPU,系数为5(只是我的系数猜测),可以用于图像上传。
POOL_SIZE = NUM_OF_CPU_CORE * coeffiecient;
答案 1 :(得分:2)
submit()
向队列添加任务并返回Future
。 execute()
不会返回Future
。另见here。您观察到的不同排序可能会发生在submit()
内发生的额外管理的副作用,并且可能无关紧要。 (但请参阅@ fmucar的答案......)
不确定您的问题是什么......
根据您要上传的图像数量调整线程池的大小没有意义 - 可能只有少量线程就足够了,因为您只是想保留一些TCP流。每张图片一个帖子,如果图片列表很大,就不会给你买任何东西。
如果您仅在知道上传完成时收集Futures
,请考虑以下其中一项:
invokeAll()
,只会阻止所有提交的任务完成(参见my answer here for more details)CompletionService
编辑添加:好捕获,@ fmucar,对记录器行中.get()
的调用强制顺序,因此线程池是浪费。
这是尝试给你一个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.