簡體   English   中英

如何在 Java 中有理由中斷線程/未來/執行程序?

[英]How can I interrupt a thread/future/executor with reason in Java?

我想知道為什么給定線程被中斷。 它是否被我(我的代碼的一部分)、其他庫或任何其他原因打斷了?

現在我可以通過

Thread.interrupt()

取消未來

Future.cancel(boolean mayInterruptIfRunning)

通過以下方式關閉 Executor

ExecutorService.shutdown() or ExecutorService.shutdownNow()

但是,他們都沒有給我發送原因的選項(執行中斷的信息)。 換句話說,我不能用更詳細的消息或原因拋出和捕獲 InterruptedException。

編輯:基於 Glains 解決方案,我准備了一個類似的解決方案,但使用了 Callable

public class MyCallable<T> implements Callable<T> {
    private final Callable<T> callable;

    private volatile Thread thread;
    private volatile String interruptReason;

    public MyCallable(final Callable<T> callable) {
        this.callable = callable;
        this.thread = null;
    }

    @Override
    public T call() throws Exception {
        this.thread = Thread.currentThread(); // not getCurrentThread()
        try {
            return callable.call();
        }
        catch (InterruptedException e) {
            System.out.println("Thread is interrupted: " + this.interruptReason);
        }
    }

    public void interrupt(String interruptReason) {
        this.interruptReason = interruptReason;
        thread.interrupt();
    }
}

為此,您必須編寫自定義 API,因為無法以特定原因中止Thread 要使Runnable能夠被中斷,您可以創建一個提供此功能的自定義接口:

public interface Interruptable {

    default void interrupt() {
        interrupt(Reason.unknown());
    }

    void interrupt(Reason reason);
}

定義的原因可以是任何東西,但以下可能適合您的用例:

public class Reason {

    public static Reason unknown() {
        return new Reason("unknown");
    }

    private final String reason;

    public Reason(String reason) {
        this.reason = reason;
    }

    public String getReason() {
        return reason;
    }
}

現在,您將不得不調整您的Runnable實現,以便它可以被中斷。 請注意,以下解決方案優雅地中斷了線程,這意味着當前迭代將完成,但不會開始新的迭代。 如果要真正中斷線程,則需要存儲對執行Runnable實例run方法的線程的引用,因為不會從同一線程調用interrupt方法。 然后您可以在該引用上調用Thread.interrupt

public class MyRunnable implements Runnable, Interruptable {

    private final AtomicBoolean running = new AtomicBoolean(false);

    @Override
    public void interrupt(Reason reason) {
        running.set(false);
        System.out.println("Thread is interrupted: " + reason.getReason());
    }

    @Override
    public void run() {
        running.set(true);
        while (running.get()) {
            // do work
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM