首页 > 解决方案 > 我可以在 JAVA 超时后终止 Runnable 吗?

问题描述

        ScriptEngineManager scriptEngineMgr = new ScriptEngineManager();
        ScriptEngine jsEngine = scriptEngineMgr.getEngineByName("nashorn");

        Mono.fromRunnable(() -> {
            System.out.println("11111");
            try {
                System.out.println("2222");
                jsEngine.eval("print(\"hello\");while(1);");
            } catch (ScriptException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            System.out.println("3333");

        }).timeout(Duration.ofMillis(2000)).doOnError(Exception.class, e -> {
            System.out.println("4444");
            System.out.println(e.toString());
        }).onErrorResume(Exception.class, e -> {
            System.out.println("5555");
            return Mono.error(e);
        }).block();

        System.out.println("end!!!");

这段代码永远不会结束。它显示“java.util.concurrent.TimeoutException:在'source(MonoRunnable)'中没有观察到任何项目或终端信号在2000毫秒内(并且没有配置回退)”。

我想在 2 秒内终止它,然后看到“结束!!!”。

我怎么解决这个问题?

标签: javaspringspring-bootspring-webfluxreactive

解决方案


这是反应器的一个相当奇怪的用法 - 如果你真的想在 2 秒后超时,那么更正常/更好的方法可能是eval()在一个新线程中生成你的线程,并interrupt()在一段时间后处理该线程(然后InterruptedException酌情处理.)

但是,要直接回答这个问题,您onErrorResume()在链末尾的调用本身会返回一个(本质上是它正在处理Mono.error的相同错误的克隆。)当您调用时,会抛出此异常Monoblock()

相反,您可能想要返回Mono.empty()而不是Mono.error(e)在该onErrorResume()块中。


推荐阅读