【并发编程】- ExecutorService的invokeAny方法超时设置和多种异常处理

272 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

方法invokeAny(Collection Tasks,timeout,timeUnit)超时设置

运行类执行代码如下:

public class InvokeAnyRun {
    public static void main(String[] args) {

        try {
            List list = new ArrayList();
            list.add(new FCallable());
//        list.add(new SCallable());
            ExecutorService executorService = Executors.newCachedThreadPool();
            String result = (String) executorService.invokeAny(list,1, TimeUnit.SECONDS);
            System.out.println("已完成任务的返回值:"+result);
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("进入捕获到 InterruptedException");
        } catch (ExecutionException e) {
            e.printStackTrace();
            System.out.println("进入捕获到 ExecutionException");
        } catch (TimeoutException e) {
            e.printStackTrace();
            System.out.println("进入捕获到 TimeoutException");
        }
    }
}

运行结果如下:

FCallable i:1234566

FCallable i:1234567

com.ozx.concurrentprogram.executor.service.FCallable 结束时间: 1661589890529

在出现超时异常时,可以使用if(Thread.currentThread().isInterrupted() == true)判断和throw new InterruptedException()结合使用线程中断执行。

​ 如果只有一个任务被执行,这个任务既超时又出现了异常,运行情况如下:

线程执行代码如下:

public class FCallable implements Callable<String> {

    @Override
    public String call() throws Exception {
        try{
            System.out.println(super.getClass().getName()+"  开始时间:  "+System.currentTimeMillis());
            for (int i = 0; i < 123456 ; i++) {
                Math.random();
                Math.random();
                Math.random();
                System.out.println("FCallable i:"+(i+1));
                if(Thread.currentThread().isInterrupted() == true){
                    System.out.println(super.getClass().getName()+"中断了......");
                    throw new NullPointerException();
                }
            }
            System.out.println(super.getClass().getName()+"  结束时间:  "+System.currentTimeMillis());
        }catch(Exception e){
            e.printStackTrace();
            System.out.println("通过显式try-catch捕获到异常,异常原因:"+e.getMessage());
            throw  e;
        }
        return super.getClass().getName();
    }
}

运行类执行代码如下:

public class InvokeAnyRun {
    public static void main(String[] args) {

        try {
            List list = new ArrayList();
            list.add(new FCallable());
            ExecutorService executorService = Executors.newCachedThreadPool();
            String result = (String) executorService.invokeAny(list,1, TimeUnit.SECONDS);
            System.out.println("已完成任务的返回值:"+result);
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("进入捕获到 InterruptedException");
        } catch (ExecutionException e) {
            e.printStackTrace();
            System.out.println("进入捕获到 ExecutionException");
        } catch (TimeoutException e) {
            e.printStackTrace();
            System.out.println("进入捕获到 TimeoutException");
        }
    }
}

运行结果如下:

FCallable i:1

FCallable i:2

FCallable i:3

......

FCallable i:35480

FCallable i:35481

FCallable i:35482

进入捕获到 TimeoutException

com.ozx.concurrentprogram.executor.service.FCallable中断了......

通过显式try-catch捕获到异常,异常原因:null

java.util.concurrent.TimeoutException at java.util.concurrent.AbstractExecutorService.doInvokeAny(AbstractExecutorService.java:184) at java.util.concurrent.AbstractExecutorService.invokeAny(AbstractExecutorService.java:225) at com.ozx.concurrentprogram.executor.controller.InvokeAnyRun.main(InvokeAnyRun.java:27) java.lang.NullPointerException at com.ozx.concurrentprogram.executor.service.FCallable.call(FCallable.java:23) at com.ozx.concurrentprogram.executor.service.FCallable.call(FCallable.java:10) at java.util.concurrent.FutureTask.runcapture(FutureTask.java:266) at java.util.concurrent.FutureTask.run(FutureTask.java) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.runcapture(FutureTask.java:266) at java.util.concurrent.FutureTask.run(FutureTask.java) 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)

从运行结果看出同时存在java.util.concurrent.TimeoutException超时异常和java.lang.NullPointerException空指针异常时,其中超时异常是在main线程中捕获到的,而空指针异常是在Callable中捕获到的。