簡體   English   中英

Java如何等待線程退出或用戶按下Enter鍵

[英]Java How to Wait Until Thread Exits or User Presses Enter

當用戶按下Enter或另一個線程完成其工作時,我需要退出應用程序。 我過去完成此操作的方式如下:

// Main
final Worker worker = new Worker();
final Thread workerThread = new Thread(worker::run);
workerThread.start();
try {
    System.in.read();
} catch (final IOException e) {
    // The worker thread finished executing
}

// Worker::run
public void run() {
    ...
    System.in.close();
}

以前這似乎工作得很好,但是最近在執行一些重構后就中斷了。 現在,在另一個線程中對System.in.close()的調用中,該線程被無限期地掛在FileInputStream :: close的本機方法close0 誰能解釋為什么此方法調用會無限期掛起,就像出現死鎖情況一樣?

我確實有一個解決方法,如下所示:

// Main.java
private static final Object waitObject = new Object();

private static boolean isRunning = true;

private static void notifyWaitObject() {
    synchronized (waitObject) {
        isRunning = false;
        waitObject.notify();
    }
}

public static void main(final String[] args) {
    // Create a thread to wait until enter is pressed
    final Thread waitThread = new Thread(() -> {
        try {
            System.in.read();
        } catch (final IOException e) {
            // Eat the exception
        } finally {
            notifyWaitObject();
        }
    }, "User Input Thread");
    waitThread.setDaemon(true);
    waitThread.start();

    // Create a worker thread
    final Worker worker = new Worker();
    final Thread workerThread = new Thread(() -> worker.run(Main::notifyWaitObject));
    workerThread.start();

    // Wait until either the worker threads are done, or enter is pressed
    synchronized (waitObject) {
        if (isRunning) waitObject.wait();
    }
}

// Worker.java
public void run(final Runnable exitNotifier) {
    ...
    exitNotifier.run();
}

但是,對於似乎應該相對簡單的內容,上述內容似乎不必要。 有誰知道以線程安全的方式實現此目標的更好方法?

我不知道有任何可靠的方法來停止執行舊java.io流的a / ik的線程,而afaik從未起作用。 但是,正如您說的那樣,如果要退出應用程序(工作器或I / O),則可以使用:

ExecutorService es = Executors.newFixedThreadPool(2);

es.invokeAny(Arrays.asList(
    () -> { worker.run(); return null; },
    () -> System.in.read() ));

es.shutdown();
System.exit(0);

當一個作業完成時, invokeAny將返回,甚至在中斷的情況下取消另一個作業,在這種情況下,它會支持該作業。

請注意,由於停止System.in.read()操作實際上並不起作用,因此如果沒有提供控制台輸入,將有一個懸空的工作線程仍在執行System.in.read() ,但是退出JVM將終止所有線程無論如何。

暫無
暫無

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

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