CompletionService测试类

最近看了CompletionService使用总结-CSDN博客 

学习了一下里面的用法,自己写了个测试类

记录一下,个人感觉,这里主要是把线程池套在ExecutorCompletionService这个壳里,然后用它的take和poll方法

/**
 * @Author: XXX
 * @CreateTime: 2023 - 10 - 27
 * @Description: 接口CompletionService的功能是以异步的方式一边生产新的任务,一边处理已完成任务的结果,
 * 这样可以将执行任务与处理任务分离开来进行处理。使用submit执行任务,使用take取得已完成的任务,并按照完成这些任务的时间顺序处理它们的结果。
 */
public class CompletionServiceTest {
    /**
     * 接口CompletionService的结构比较简洁,仅有一个实现类ExecutorCompletionService,
     * 类ExecutorCompletionService需要依赖于Executor对象,大部分的实现也就是实现线程池ThreadPoolExecutor对象。
     *
     * @param args
     */
    public static void main(String[] args) throws Exception {
        // 设置线程池,3个核心线程
        ThreadPoolExecutor threadPoolExecutor =
                new ThreadPoolExecutor(3, 3, 1000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10));
        ExecutorCompletionService<Object> executorCompletionService = new ExecutorCompletionService<>(threadPoolExecutor);

//        // 使用take()方法,谁先做完把谁取出来
//        test1(executorCompletionService);
//        // 使用poll()方法,直接开始取,取不到就null
//        test2(executorCompletionService);
//        // 使用poll(long timeout,TimeUnit unit) 方法,到了规定的时间开始取,取不到返回null
//        test3(executorCompletionService);
          // 使用get()方法,等到指定的future执行完了再get它的结果
        test4(executorCompletionService);


    }

    /**
     * 方法take()取得最先完成任务的Future对象,谁执行时间最短谁最先返回,即方法take()是按任务执行的速度,从快到慢的顺序获得Future对象。
     *
     * @param executorCompletionService
     * @throws InterruptedException
     * @throws ExecutionException
     */
    private static void test1(ExecutorCompletionService<Object> executorCompletionService) throws Exception {
        // 设置5个任务
        for (int i = 0; i < 5; i++) {
            Integer number = i;
            // Future和Callable一般是配合使用起来的。相比Runnable,Callable多了返回值,可以返回结果/异常,由Future对象接收。
            executorCompletionService.submit(() -> {
                task(number);
            }, "任务" + number + "已完成");
        }
        for (int i = 0; i < 5; i++) {
            Thread.sleep(5);
            System.out.println(executorCompletionService.take().get());
        }
    }

    /**
     * 方法poll()的作用是获取并移除表示下一个已完成任务的Future,如果不存在这样的任务,则返回null,方法poll()无阻塞的效果。
     * take和poll的区别:
     * take()如果队列中没有数据,则线程会wait并释放CPU,而poll()则会直接返回null。
     *
     * @param executorCompletionService
     * @throws Exception
     */
    private static void test2(ExecutorCompletionService<Object> executorCompletionService) throws Exception {
        // 设置5个任务
        for (int i = 0; i < 5; i++) {
            Integer number = i;
            // Future和Callable一般是配合使用起来的。相比Runnable,Callable多了返回值,可以返回结果/异常,由Future对象接收。
            executorCompletionService.submit(() -> {
                task(number);
            }, "任务" + number + "已完成");
        }
        for (int i = 0; i < 5; i++) {
            // poll队列的时候还没任务做完,所以返回null,这时候get()就空指针了
            System.out.println(executorCompletionService.poll());
        }
    }

    /**
     * 方法Future<V> poll(long timeout,TimeUnit unit)的作用是等待指定的timeout时间,在timeout时间之内获取到值时立即向下继续执行,如果超时也立即向下执行。
     *
     * @param executorCompletionService
     * @throws Exception
     */
    private static void test3(ExecutorCompletionService<Object> executorCompletionService) throws Exception {
        // 设置5个任务
        for (int i = 0; i < 5; i++) {
            Integer number = i;
            // Future和Callable一般是配合使用起来的。相比Runnable,Callable多了返回值,可以返回结果/异常,由Future对象接收。
            executorCompletionService.submit(() -> {
                task(number);
            }, "任务" + number + "已完成");
        }
        long start = System.currentTimeMillis();
        for (int i = 0; i < 5; i++) {
            // poll队列的时候还没任务做完,所以返回null,这时候get()就空指针了
            System.out.println(executorCompletionService.poll(2000, TimeUnit.MILLISECONDS).get());
            System.out.println("耗时:" + (System.currentTimeMillis() - start));
        }
    }

    /**
     * get方法
     * 如果任务没有完成,使用get()就会被阻塞,而且没有异常的处理方法,只能去在get的时候catch
     *
     * @param executorCompletionService
     * @throws Exception
     */
    private static void test4(ExecutorCompletionService<Object> executorCompletionService) throws Exception {
        // 设置1个任务
        Integer number = 1;
        // Future和Callable一般是配合使用起来的。相比Runnable,Callable多了返回值,可以返回结果/异常,由Future对象接收。
        Future<Object> future = executorCompletionService.submit(() -> {
            task(number);
        }, "任务" + number + "已完成");
        System.out.println(future.get());
    }


    /**
     * 执行的任务,任务1--1000ms,任务2--3000ms,其余任务10ms
     *
     * @param number
     */
    public static void task(Integer number) {
        try {
            switch (number) {
                case 0:
                    Thread.sleep(1000);
                    System.out.println("线程:" + Thread.currentThread().getName() + "执行任务0完成");
                    break;
                case 1:
                    Thread.sleep(5000);
                    System.out.println("线程:" + Thread.currentThread().getName() + "执行任务1完成");
                    break;
                default:
                    Thread.sleep(10);
                    System.out.println("线程:" + Thread.currentThread().getName() + "执行任务" + number + "完成");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值