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

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

List<Future> futureList = new ArrayList<Future>(); 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()函数是否具有相同的效果?

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

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

来自@ andersoj的回答;

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

POOL_SIZE = NUM​​_OF_CPU_CORE * coeffiecient;

submit()将任务添加到队列并返回Futureexecute()不返回Future 。 另见这里 。 您观察到的不同排序可能会发生在submit()内部发生的附加管理的副作用,并且可能无关紧要。 (但看@fmucar的回答……)

不确定你的问题究竟是什么……

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

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

  • 使用invokeAll() ,它将一直阻塞,直到所有提交的任务完成为止(详情请参阅我的答案 )
  • 使用CompletionService

编辑添加 :好捕获,@ fmucar,在记录器行中调用.get()强制顺序,所以线程池是浪费。

invokeAll()示例

这是尝试给你一个invokeAll()示例; 不确定它是否与您的代码完全匹配。

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