【并发编程】- ExecutorService的invokeAll方法先慢后快情况

60 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

方法invokeAll(Collection tasks,long timeout,TimeUnit unit)先慢后快情况

invokeAll(Collection tasks,long timeout,TimeUnit timeUnit)方法的作用是如果全部任务在指定情况内没有完成,则出现异常。

第一个线程执行代码如下:

public class OFirstCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println(super.getClass().getName()+ "  线程执行开始时间:"+ System.currentTimeMillis());
        for (int i = 0; i <  123456; i++) {
            Math.random();
            Math.random();
            Math.random();
            System.out.println(super.getClass().getName()+(i+1));
        }
        System.out.println(super.getClass().getName()+"  线程执行结束时间:" + System.currentTimeMillis());
        return super.getClass().getName();
    }
}

第二个线程执行代码如下:

public class OSecondCallable implements Callable<String> {
        @Override
        public String call() throws Exception {
            System.out.println(super.getClass().getName()+ "线程执行开始时间:"+ System.currentTimeMillis());
            for (int i = 0; i <  8; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println(super.getClass().getName()+(i+1));
            }
            System.out.println(super.getClass().getName()+"线程执行结束时间:" + System.currentTimeMillis());
            return super.getClass().getName();
        }
}

运行类执行代码如下:

public class invokeAllRun {
    public static void main(String[] args) {
        OFirstCallable oFirstCallable = new OFirstCallable();
        OSecondCallable oSecondCallable = new OSecondCallable();
        List<Callable<String>> list = new ArrayList<>();
        list.add(oFirstCallable);
        list.add(oSecondCallable);
        ExecutorService executorService = Executors.newCachedThreadPool();
        System.out.println("invokeAll方法执行开始时间:" + System.currentTimeMillis());
        try {
            List<Future<String>> futureList = executorService.invokeAll(list,2,TimeUnit.SECONDS);
            System.out.println("invokeAll方法执行结束时间: " + System.currentTimeMillis());
            for (int i= 0;i< futureList.size();i++) {
                System.out.println("第"+(i+1)+"次循环");
                System.out.println("返回的结果:" + futureList.get(i).get());
            }
            System.out.println("结束时间: "+System.currentTimeMillis());
        } catch (InterruptedException e) {
            System.out.println("进入 InterruptedException 异常捕获");
            e.printStackTrace();
        } catch (ExecutionException e) {
            System.out.println("进入 ExecutionException 异常捕获");
            e.printStackTrace();
        }
    }
}

运行结果如下: com.ozx.concurrentprogram.executor.service.october.OFirstCallable 123 第1次循环

从运行结果看出没输出第一个线程和第二个线程的结果返回值字符串,

使用invokeAll()方法出现超时后,调用 Future对象的get()方法时出现的是CancellationException异常,而不是invokeAny()方法抛出来的TimeoutException异常。

如果使用invokeAny()方法时都没有正确的返回结果值时,则说明最后Callable跑出来的异常在主线程中是会被处理的。