【并发编程】- 线程池使用get(long timeout,TimeUnit unit)方法指定时间等待获取返回值

403 阅读2分钟

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

线程池使用get(long timeout,TimeUnit unit)方法

方法get(long timeout,TimeUnit unit)的作用是在指定的最大时间内等待获取返回值。

线程执行代码如下:

@Slf4j
public class FourthCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        Thread.sleep(10000);
        log.info("休眠 10秒执行完毕");
        return simpleDateFormat.format(new Date());
    }
}

运行类代码如下:

@Slf4j
public class LimitedAcquisitionTimeRun {
    public static void main(String[] args) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        FourthCallable fourthCallable = new FourthCallable();
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 10, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
        log.info("开始时间:{}",simpleDateFormat.format(new Date()));
        Future<String> future = threadPoolExecutor.submit(fourthCallable);
        try {
            log.info("返回值:{}",future.get(5,TimeUnit.SECONDS));
            log.info("结束时间:{}",simpleDateFormat.format(new Date()));

        } catch (InterruptedException e) {
            log.error("进入 捕获InterruptedException异常");
            e.printStackTrace();
        } catch (ExecutionException e) {
            log.error("进入 捕获ExecutionException异常");
            e.printStackTrace();
        } catch (TimeoutException e) {
            log.error("进入 捕获TimeoutException异常");
            e.printStackTrace();
        }
    }
}

运行结果如下:

16:23:25.241 [main] INFO com.ozx.concurrentprogram.executor.controller.LimitedAcquisitionTimeRun - 开始时间:16:23:25

16:23:30.314 [main] ERROR com.ozx.concurrentprogram.executor.controller.LimitedAcquisitionTimeRun - 进入 捕获TimeoutException异常

java.util.concurrent.TimeoutException at java.util.concurrent.FutureTask.get(FutureTask.java:205) at com.ozx.concurrentprogram.executor.controller.LimitedAcquisitionTimeRun.main(LimitedAcquisitionTimeRun.java:24)

16:23:35.310 [pool-1-thread-1] INFO com.ozx.concurrentprogram.executor.service.FourthCallable - 休眠 10秒执行完毕

从运行结果看来程序超时后出现异常,进入捕获TimeoutException异常

异常的处理

接口Callable任务在执行时有可能会出现异常,那在Callable中异常是怎样处理呢?

线程执行代码如下:

@Slf4j
public class FourthCallable implements Callable<String> {

    private String name;
    
    public FourthCallable(String name){
        super();
        this.name=name;
    }
    
    @Override
    public String call() throws Exception {
            Integer.parseInt("a");
            return "返回值:"+name;
    }
}

运行类代码如下:

@Slf4j
public class ExceptionRun {
    public static void main(String[] args) {
        FourthCallable fourthCallable = new FourthCallable("Gxin");
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2, 3, 20, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
        Future<String> future = threadPoolExecutor.submit(fourthCallable);
        try {
            String result = future.get();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            log.error("线程代码出现错误");
            e.printStackTrace();
        }
    }
}

运行结果如下:

17:19:27.277 [main] ERROR com.ozx.concurrentprogram.executor.controller.ExceptionRun - 线程代码出现错误

java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: "a" at java.util.concurrent.FutureTask.report(FutureTask.java:122) at java.util.concurrent.FutureTask.get(FutureTask.java:192) at com.ozx.concurrentprogram.executor.controller.ExceptionRun.main(ExceptionRun.java:20)

Caused by: java.lang.NumberFormatException: For input string: "a" at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) at java.lang.Integer.parseInt(Integer.java:580) at java.lang.Integer.parseInt(Integer.java:615) at com.ozx.concurrentprogram.executor.service.FourthCallable.call(FourthCallable.java:30) at com.ozx.concurrentprogram.executor.service.FourthCallable.call(FourthCallable.java:14) at java.util.concurrent.FutureTask.run$$$capture(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)

从运行结果看出线程执行出现错误,异常被捕获到了,出现异常就进入了catch语句,不再继续执行get()方法获取返回值结果,这情况与通过for循环调用get()方法时的效果是一样的,不再继续执行for循环,而是直接进入catch捕获异常代码块。