Java运行时不是操作系统运行的任务/计算(图)

如果您真的可以取消它们,这完全取决于您并行运行的任务/计算。请记住,Java 运行时不是操作系统,您不能像处理进程那样强制线程终止。

因此,如果您想中断长时间运行的计算,您必须以某种方式写入时间,以便他们定期检查是否应该停止执行。对于等待其他一些东西(睡眠、在其他线程上同步等),这是一种完全不同的策略:您可以中断这些线程,代码将得到一个 InterruptedException ,它可以用于实际停止代码而无需与代码 。

我在这里准备了一个小例子来向您展示区别:

package examples.stackoverflow.q71322315;
import java.util.concurrent.*;
public class Q71322315 {
    public static final long COUNTER = 10000000000L;
    public static final boolean SLEEP = false;
    private static final ExecutorService taskExec = Executors.newCachedThreadPool();
    public static void timedRun(Runnable r, long timeout, TimeUnit unit) throws InterruptedException {
        Future task = taskExec.submit(r);
        try {
            task.get(timeout, unit);
            System.out.println("completed");
        } catch (TimeoutException e) {
            // task will be cancelled below
            System.out.println("timeout");
        } catch (ExecutionException e) {
            System.out.println("exex");
            // exception thrown in task; rethrow
            throw new RuntimeException(e.getCause());
        } finally {
            // Harmless if task already completed
            task.cancel(true); // interrupt if running
        }
    }
    public static void main(String[] args) throws InterruptedException {
        timedRun(new Task(SLEEP), 2000, TimeUnit.MILLISECONDS);
        taskExec.shutdown();
        System.out.println("finish");
    }
    private static class Task implements Runnable {
        private final boolean sleep;
        private Task(boolean sleep) {
            this.sleep = sleep;
        }
        @Override
        public void run() {
            try {
                if (sleep) {
                    Thread.sleep(5000L);
                } else {
                    longRunningMethod(COUNTER);
                }
                System.out.println("Success");
            } catch (Exception e) {
                e.printStackTrace();
                if (e instanceof InterruptedException) {
                    Thread.currentThread().interrupt();
                }
            }
        }
        private void longRunningMethod(long counter) {
            for (long y = 0; y < counter; y++) {
                Math.sqrt(y);
            }
        }
    }
}

该示例基于已经提到的 Java Concurrency in Practice 中的一些示例代码 – “7.10 Cancels a task using a Future”。

上面的代码执行一个长时间运行的计算并且不关心任何中断。(您可能需要通过在末尾添加零来增加 COUNTER 的值,直到整个方法花费超过 2 秒。)

您将看到您首先收到一条“超时”消息,指示任务未在要求的超时时间内完成。但代码继续运行并打印“完成”和“成功”。

当您将 SLEEP 常量翻转为 true 时,它​​将改为使用对 Thread.sleep() 的可中断调用,并且输出将不包含“成功”消息。

在您设法构建可取消/可中断的计算后,您可以设置多个线程,每个线程并行执行 timedRun 执行,因此任务并行启动并在超时后中断。

这不包括结果的收集,但您可以收集结果或计算超时任务,而不是完成和超时的系统输出。p>

(如果您想在生产中使用该代码,请彻底清理它,它确实有一些巨大的气味,不应该在任何生产就绪代码中;-)

© 版权声明
THE END
喜欢就支持一下吧
点赞210 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片