打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
Java:如何实现代码超时功能?

Java:如何实现代码超时功能?

  • public static void function() {
    // 代码1    // 代码2    // 代码3}

如果代码2执行时间过长则不再执行(代码2没有抛出TimeoutException,只是没按照规定时间执行完),继续执行后面的代码3该如何实现呢?

下面是代码超时功能的一种实现

   public class Timeout {    public static void main(String[] args) throws InterruptedException, ExecutionException {        ExecutorService exec = Executors.newFixedThreadPool(1);        Callable<Integer> call = new Callable<Integer>() {            public Integer call() throws Exception {                Thread.sleep(1000 * 5);// 耗时操作                return 1;            }        };        try {            Future<Integer> future = exec.submit(call);            int ret = future.get(1000 * 1, TimeUnit.MILLISECONDS); // 任务处理超时时间设为 1 秒            System.out.println("任务执行结果:" + ret);        } catch (TimeoutException e) {            e.printStackTrace();        } catch (Exception e) {            e.printStackTrace();        }        exec.shutdown();    }}

但这种方法的问题是新启动了一个线程,并没有阻塞,也就是我的代码3可能先于Timeout执行完,顺序不满足预期,前辈有什么好办法呢?

1

如果代码2执行时间过长则不再执行

“不再执行”是什么意思?它既然已经开始执行了,你是要强制停掉执行代码2的线程吗?还是只是不管它了,继续执行后面的代码3?

写了个小例子,可以简单实现你的要求

import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;public class Main {    public static void main(String[] args) throws InterruptedException {        ExecutorService es = Executors.newFixedThreadPool(1);        es.execute(new Runnable() {            @Override            public void run() {                int count = 7;                while (count > 0) {                    System.out.println(1);                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        // 退出执行                        System.out.println("interrupt, then quit");                        return;                    }                    count--;                }            }        });        // 关闭线程池        es.shutdown();        // 阻塞操作,等待5s        boolean finished = es.awaitTermination(5, TimeUnit.SECONDS);        // 如果过了5s线程还没有完成, 强制关闭, interrupt Runnable 线程,  进入 InterruptedException 处理流程        if (!finished) {            es.shutdownNow();        }        System.out.println("task 3");    }}
  • 我们写一个有超时功能的 Callable:
import java.util.concurrent.*;public class TimeoutCallable<V> implements Callable<V> {    private final Callable<V> callable;    private final V timeoutV;    private final long timeout;    /**     * 构造一个 TimeoutCallable     *     * @param callable 要运行的 Callable     * @param timeout Callable 的最大运行时间     * @param timeoutV Callable 超时的返回结果     */    public TimeoutCallable(Callable<V> callable, long timeout, V timeoutV) {        this.timeout = timeout;        this.callable = callable;        this.timeoutV = timeoutV;    }    @Override    public V call() throws Exception {        ExecutorService executor = Executors.newSingleThreadExecutor();        Future<V> future = executor.submit(callable);        V v = null;        try {            v = future.get(timeout, TimeUnit.MILLISECONDS);        } catch (TimeoutException ex) {            System.out.println("Callble 超时");        }        executor.shutdownNow(); // 给线程池中所有正在运行的线程发送 中断 信号        return v != null ? v : timeoutV;    }}

然后试验:

import java.util.concurrent.*;public class Test {    public static void main(String[] args) throws Exception {        Callable<Integer> callable = () -> {            int N = 4;            int sum = 0;            for (int i = 0; i < N; i++) {                // Thread.sleep 方法是可以响应中断的,                // 如果你的代码需要“超时则线程结束”的效果,那么你的代码也应该要能够响应中断                Thread.sleep(1000);                sum += i;            }            return sum;        };        // 代码2, 代码2 运行的最长时间为 timeout        int timeout = 3000;        Integer timeoutValue = -1;        TimeoutCallable<Integer> timeoutCallable = new TimeoutCallable<>(callable, timeout, timeoutValue);        ExecutorService executor = Executors.newSingleThreadExecutor();        Future<Integer> future = executor.submit(timeoutCallable);        Integer result = future.get();        executor.shutdown();        // end 代码2        // 代码3        if (timeoutValue.equals(result)) {            System.out.println("--任务超时--");        } else {            System.out.println("任务结果:" + result);        }        // end 代码3    }}

callable 的运行时间为 4 s,但我们设置的超时时间为 3 s,所以代码运行结果就是:

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Java线程(六):Callable和Future
python如何实现任务超时处理?
第二十五天 多线程-常用方法&线程池【悟空教程】
Java异步编程接口:Callable和Future | Aoho''s Blog
Java创建并执行线程的四种方法
java多线程、线程池的实现
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服