Java并发编程(五)CompletionService

CompletionService

功能介绍

java.util.concurrent.CompletionService 是对 ExecutorService 的一个功能增强封装,优化了获取异步操作结果的接口。

Future 的 get() 方法会阻塞线程降低代码与性效率,使用CompletionServie可以解决这个问题。

CompletionService 本身不包含线程池,创建它的实例之前,先要创建一个 ExecutorService。下面是一个例子:

ExecutorService executor = Executors.newFixedThreadPool(4);
CompletionService<String> completionService = new ExecutorCompletionService<>(executor);

//向 CompletionService 提交任务的方式与 ExecutorService 一样:
completionService.submit(() -> "Hello");

//CompletionService不需要主动获得 Future。take() 方法返回的是最早完成的任务的结果,这个就解决了一个任务被另一个任务阻塞的问题。
String result = completionService.take().get(); 
	/**
	 * 不用等待所有线程执行完毕,而是谁先执行完毕,就返回谁的结果
	 */
    public  static void createCompletionServicesAll(String key, List<Callable> callables, Consumer< Future> consumer)  {
        CompletionService<?> completionService = new ExecutorCompletionService<>(getExecutor(key));
        for (Callable callable : callables) {
            completionService.submit(callable);
        }
        try {
            for (int i = 0; i < callables.size(); i++) {
                consumer.accept(completionService.take());
            }
        } catch (InterruptedException e) {
 
            e.printStackTrace();
        }
    }
    
    /**
     * 一堆线程同时执行,谁先执行完毕那么就采用谁的结果。
     */
    public  static Object createCompletionServicesOne(String key, List<Callable> callables) throws ExecutionException {
 
        CompletionService<?> completionService = new ExecutorCompletionService<>(getExecutor(key));
        for (Callable callable : callables) {
 
            completionService.submit(callable);
        }
        Object result=null;
        try {
 
            result=completionService.take().get();
        } catch (InterruptedException e) {
 
            e.printStackTrace();
        }

        return result;
    }


	@Test
    public  void test(){
        List<Callable> callables=new LinkedList<>();
        for (int i = 0; i < 100; i++) {
 
            int finalI = i;
            callables.add(()->{
//                throw  new Exception("---");
                int random = new Random().nextInt(100);
                Thread.sleep(random);
                System.out.println("sleep:"+random+"s后返回结果:"+finalI);
                return finalI;
            });
        }
//        Collections.shuffle(callables);

        ExecutorUtils.createCompletionServicesAll("test",callables,(o)->{
 
            try {
 
                System.out.println(o.get()); //如果某个线程出现异常则抛出异常我们这里可以捕捉到
            } catch (InterruptedException | ExecutionException e) {
 
                e.printStackTrace();
            }
        });
    }

    @Test
    public  void test1(){
        List<Callable> callables=new LinkedList<>();
        for (int i = 0; i < 100; i++) {
            int finalI = i;
            callables.add(()->{
//                throw  new Exception("---");
                int i1 = new Random().nextInt(1000);
                Thread.sleep(i1);
                System.out.println("等待:"+i1+"s后返回结果:"+finalI);
                return finalI;
            });
        }

        try {
            //获取第一个执行完毕的结果
            Integer test = (Integer)ExecutorUtils.createCompletionServicesOne("test", callables);
            System.out.println("result: " + test);
        } catch (ExecutionException e) {
 
            e.printStackTrace();
        }
    }	

pool() 方法可以用来获取并移除表示下一个以完成任务的Future 如果不存在则返回null 并且不会阻塞。 也可以在指定的时间内等待,超时后继续向下运行。

CompletionService 主要用来解决FutureTask阻塞的问题,可以更加高效的处理Future的返回 获取最先执行玩的任务的返回值进行处理。

你可能感兴趣的:(Java初学者,java,jvm,开发语言)