【Java】CompletionService 使用

来源:互联网 发布:java视频教程数组 编辑:程序博客网 时间:2024/06/07 05:44

使用线程池的submit方法时,可以返回一个Future,我们可以通过这个Future来获得任务的返回值。那么通常的场景是,我们通过多个任务来获取到了返回值,之后就需要对返回值进行处理,此时我们需要把每一个Future放进一个容器里,然后用一个循环处理。不过这里还是有问题的,我们知道通常的容器是不允许一边读取,一边修改的,会抛出一个ConcurrentModificationExceptoin,一般的容器遍历都是静态的,但是这里的容器却不是,它时时刻刻都有可能被放入一个结果,但是什么时候谁也不知道,而且它有可能是是空的。所以这个容器与以往的场景不同。我们需要支持之前提到的特性。

这其实就是CompletionService的用途,它已经为我们维护了这个队列,它会自动把执行完的任务结果放入队列中,我们可以使用take方法或者poll来获取结果。take在队列为空时会被阻塞,而poll返回null。这样我们编写上述代码就会简单得多,不同再去担心自己维护一个结果的队列的。

下面是一个UI中很常见的例子,异步加载不同的资源,像文本这种的我们可以直接渲染,但是图片这种的,我们需要先下载然后加载,可以让每一个下载异步执行,把结果放入一个队列,再从队列里面拿下好的图片渲染。

package ThreadTest;import java.util.concurrent.Callable;import java.util.concurrent.CompletionService;import java.util.concurrent.ExecutionException;import java.util.concurrent.ExecutorCompletionService;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Future;public class PageRender {public void rend(Source source){ExecutorService e = Executors.newFixedThreadPool(10);CompletionService<Image> ce = new ExecutorCompletionService<Image>(e);for(String url : source.urls){ce.submit(new Callable<Image>() {@Overridepublic Image call() throws Exception {return download(url);}});}rendTxt(source.txt);for(int i = 0 ; i < source.urls.size(); i++){try {Future<Image> future = ce.take();Image img = future.get();rendImage(img);} catch (InterruptedException e1) {e1.printStackTrace();} catch (ExecutionException e1) {e1.printStackTrace();}}e.shutdown();}Image download(String url){System.out.println("download Image" + url);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}return new Image();}void rendTxt(String txt){System.out.println("rendTxt");}void rendImage(Image img){System.out.println("rendImage");}}

public static void main(String[] args) {PageRender pr = new PageRender();Source source = new Source();List<String> list = new ArrayList<>();for(int i = 0 ; i < 10; i++){list.add("url " + i);}source.urls = list;source.txt = "Hello";pr.rend(source);}
结果:

download Imageurl 0

download Imageurl 2

download Imageurl 3

download Imageurl 1

download Imageurl 4

download Imageurl 5

download Imageurl 6

download Imageurl 7

rendTxt

download Imageurl 9

download Imageurl 8

rendImage

rendImage

rendImage

rendImage

rendImage

rendImage

rendImage

rendImage

rendImage

rendImage


这便是CompletionService的用途,方便我们获取每一次异步得到的结果。



原创粉丝点击