簡體   English   中英

Java while 循環未按預期循環

[英]Java while-loop not looping as expected

問題

以下 while 循環不檢查“停止”是否為真:

while (jobs.isEmpty()) {
   if (stopping) {
      running = false;
      break;
   }
}

但是,如果我在 if 語句之前插入任何其他語句,則 if 語句會可靠地進行檢查,如以下循環所示:

while (jobs.isEmpty()) {
   try {
      Thread.sleep(1000);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
   if (stopping) {
      running = false;
      break;
   }
}

當然,我希望它在沒有 1 秒延遲的情況下工作,有什么解決辦法,或者為什么它一開始就不起作用?


澄清

為了澄清這一點,我創建了一個簡單的測試 Class:

public class Test {
    static boolean stopping = false;
    static boolean running = true;

    public static void main(String[] args) throws InterruptedException {

        new Thread(() -> {
            while (true) {
                if (stopping) {
                    running = false;
                    break;
                }
            }
            System.out.println("1. Worked");
        }).start();

        new Thread(() -> {
            while (true) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (stopping) {
                    running = false;
                    break;
                }
            }
            System.out.println("2. Worked");
        }).start();

        Thread.sleep(1000);

        stopping = true;

        Thread.sleep(5000);
        System.exit(0);
    }
}

Output:

2. Worked

Process finished with exit code 0

直接的問題是對您的標志的更新在線程中不可見,並且使標志易失性解決了這個問題。 但是,有一種更好的方法來通知您的線程退出。

下面是一個使用 Thread 的中斷方法的示例:

public class Test {

    public static void main(String[] args) throws InterruptedException {

        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    System.out.println("worker is sleeping");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    // flag is cleared when exception is thrown,
                    //  and needs to be set again
                    Thread.currentThread().interrupt();
                }                
            }
            System.out.println("worker terminating");
        });
        t.start();
        System.out.println("main thread sleeping");
        Thread.sleep(1000);
        System.out.println("main thread interrupts worker and waits for it to finish");
        t.interrupt();
        t.join();
    }
}

使用中斷的好處是像 sleep 和 wait 這樣的東西知道檢查標志並可以對其做出反應(例如通過早起),這是他們不能用你的 volatile 標志做的。

運行你的例子你可以看到你必須等待工作人員完成睡眠才能檢查你的標志並發現它需要退出。 運行此示例,您可以看到即使 worker 一次休眠 10 秒,它也會快速退出以響應中斷。

暫無
暫無

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

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