java - 在 Java 中运行脚本指定的时间段

标签 java

我有一个我想运行的java代码。如果作业没有在 2 小时内完成,那么它应该被自动终止(基本上是某种定时批处理)。

如何用Java实现这一点?

最佳答案

如果您使用的是 Java 9 或更高版本,您可以执行以下超时批处理:-

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(this::longRunningTask)
                       .orTimeout(2, TimeUnit.SECONDS); 
 future.get(); // j.u.c.ExecutionException after waiting for 2 second

如果在timeout限制内完成,它将返回值(这里是一个Integer对象来响应future.get()方法)

并且,此批处理是异步(如果您不显式调用 get 方法。)

注意:这不会阻止线程完成任务,它只是在主线程中完成一个带有超时异常的 future,以便主线程可以继续。后台任务/线程仍在继续完成。 (看@Andreas评论)

一些示例:-

final CompletableFuture<Void> future =
                   CompletableFuture.supplyAsync(this::longRunningTask)
                                    .orTimeout(2, TimeUnit.SECONDS);

future.get(); // j.u.c.ExecutionException after waiting for 2 second

还有longRunningTask():-

private Void longRunningTask(){
    log.info("Thread name" + Thread.currentThread().getName());
    try {
        log.info("Going to sleep for 10 sec...");
        Thread.sleep(10*1000);
        log.info("Sleep Completed. Task Completed.");
    } catch (InterruptedException e) {
        log.info("Exception Occurred");
    }
    finally{
        log.info("Final Cleanup in progress.");
    }
    log.info("Finishing the long task.");
    return null;
}

如果你运行上面的代码,它会在主线程(其中调用 future.get())中给出执行异常,但 longRunningTask 仍然会打印 sleep 完成。任务已完成。 完成 10 秒 sleep 后。

如果您仔细观察,longRunnigThread 永远不会被中断(不会进入 catch block ),因此会正常继续,但主线程在 get() 上出现异常。

解决方法/解决方案:

使用ExecutorService并使用该Executor提交longRunnigTask future,如果超时,则关闭执行器,否则,在get()成功后关闭 如果没有超时异常。

示例:

    ExecutorService myWorkers = Executors.newFixedThreadPool(1);

    final CompletableFuture<Void> longTask = 
            CompletableFuture.supplyAsync(this::longRunningTask, myWorkers)
                .orTimeout(2, TimeUnit.SECONDS);

    try {
        longTask.get();
    } catch (InterruptedException | ExecutionException e) {
        log.info("EE... Kill the executor thread/s.");
        myWorkers.shutdownNow(); // this will interrupt the thread, catch the IntrExcep in thread and return the execution there
    }

以及稍作修改的longRunnigTask

private Void longRunningTask(){
    log.info("Thread name" + Thread.currentThread().getName());
    try {
        log.info("Going to sleep for 10 sec...");
        Thread.sleep(10*1000);
        log.info("Sleep Completed. Task Completed.");
    } catch (InterruptedException e) {
        log.info("Exception Occurred");
        return null; // this will finish the thread exce releasing all locking resources. Can be GCed then.
    }
    finally{
        log.info("Final Cleanup in progress.");
    }
    log.info("Finishing the long task.");
    return null;
}

使用这种方法,如果发生超时,它将无法完成任务(您不会在日志中看到 sleep 已完成。任务已完成。..),并且会看到, longRunningTask 线程发生异常(由于 myWorker.shutdown 导致中断)。

关于java - 在 Java 中运行脚本指定的时间段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57950990/

相关文章:

java - Wicket 6 DefaultNestedTree 未在文件夹单击时展开

java - 执行 org.apache.maven.plugins :maven-war-plugin:2. 1.1:war 时缺少必需的类

java - 为什么spring security无法获取用户名?

java - 更改 JavaFX NullPointerException 中的场景

java - Java 新手逻辑

java - 从工厂请求元素,无需对每个案例进行硬编码

java - 在java中的日期选择器上仅突出显示当月的当前日期

Java自动增长数组

java - 如何在 Kotlin/Java 中对 Numpy 数组(Python)进行 base64 解码?

java - 有没有办法将 Java 方法标记(例如注释)为永不返回?