CompletionService使用

CompletionService使用

接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成的任务的结果。这样可以将执行任务与处理处理分离开来处理。使用submit执行任务,使用take取得已经完成的任务

CompletionService,内部使用Executor框架和BlockingQueue来实现的

public class MyCallable implements Callable<String> {

    private String username;
    private long sleepValue;


    public MyCallable(String username, long sleepValue) {
        this.username = username;
        this.sleepValue = sleepValue;
    }

    @Override
    public String call() throws Exception {
        System.out.println(username);
        Thread.sleep(sleepValue);
        // if ("userName3".equals(username)){
        //    throw new Exception("自己抛出异常了");
        // }
        return "return: "+ username;
    }
}

测试:

@Test
public void testMyCallable() throws InterruptedException {


    try {
        List<MyCallable> list = new ArrayList<>();
        for (int i=1; i<=5; i++){
            MyCallable myCallable = new MyCallable("userName"+i, i*1000);
            list.add(myCallable);
        }

        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,10,
                5, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>());
        CompletionService completionService = new ExecutorCompletionService(executor);

        for (int i=0; i<5; i++){
            completionService.submit(list.get(i));
        }


        for (int i=0; i<5; i++){
            System.out.println("等待打印"+(i+1)+"个返回值");
            System.out.println(completionService.take().get());
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }

    Thread.sleep(3000);

}

结果:

userName1
userName3
userName2
等待打印1个返回值
userName4
userName5
return: userName1
等待打印2个返回值
return: userName2
等待打印3个返回值
return: userName3
等待打印4个返回值
return: userName4
等待打印5个返回值
return: userName5

如果放开注释:

等待打印1个返回值
userName1
userName2
userName3
userName4
userName5
return: userName1
等待打印2个返回值
return: userName2
等待打印3个返回值
java.util.concurrent.ExecutionException: java.lang.Exception: 自己抛出异常了
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at com.github.vspro.concurrent.MyCallableTest.testMyCallable(MyCallableTest.java:34)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
Caused by: java.lang.Exception: 自己抛出异常了
	at com.github.vspro.concurrent.MyCallable.call(MyCallable.java:21)
	at com.github.vspro.concurrent.MyCallable.call(MyCallable.java:5)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

可以看到,如果抛出异常,后面的计算结果都获取不到了

你可能感兴趣的:(concurrent)