簡體   English   中英

無法使用 break 語句退出 for 循環

[英]Can't exit for loop using break statement

public class Threading extends Thread {
    @Override
    public void run(){
        for (int i=0;i<=5;i++){
            System.out.println(Thread.currentThread().getName()+" reached "+i+" metres");
            if(i==5){
                System.out.println("WINNER IS  "+Thread.currentThread().getName().toUpperCase(Locale.ENGLISH));              
                break;
            }
        }
    }
    public static void main(String[] args) {
        Threading t1=new Threading();
        Threading t2=new Threading();
        Threading t3=new Threading();
        t1.setName("Mohit");
        t2.setName("Hary");
        t3.setName("Himanshu");
        t1.start();
        t2.start();
        t3.start();
    }
}

我想打印首先到達 5 米然后退出循環的線程的名稱。 但是這段代碼發生的事情是 for 循環一直運行,直到每個線程達到 5 米,並在達到 5 米時打印所有線程的名稱。 請告訴我為什么會發生這種情況,我該如何糾正?

如何以下列方式使用AtomicBoolean

public static class Threading extends Thread {
    private AtomicBoolean raceFinished;

    public Threading(AtomicBoolean raceFinished) {
        this.raceFinished = raceFinished;
    }

    @Override
    public void run() {
        for (int i = 0; i <= 5; i++) {
            System.out.println(Thread.currentThread().getName() + " reached " + i + " metres");
            if (i == 5) {
                if (raceFinished.getAndSet(true)) {
                    break;
                }
                System.out.println("WINNER IS  " + Thread.currentThread().getName().toUpperCase(Locale.ENGLISH));
                break;
            }
        }
    }

    public static void main(String[] args) {
        AtomicBoolean raceFinished = new AtomicBoolean(false);
        Threading t1 = new Threading(raceFinished);
        Threading t2 = new Threading(raceFinished);
        Threading t3 = new Threading(raceFinished);
        t1.setName("Mohit");
        t2.setName("Hary");
        t3.setName("Himanshu");
        t1.start();
        t2.start();
        t3.start();
    }
}

如果您不希望在找到獲勝者后繼續“比賽”,則在循環的開頭添加以下內容:

if (raceFinished.get()) {
    break;
}

但是這段代碼發生的事情是 for 循環一直運行,直到每個線程達到 5 米,並在達到 5 米時打印所有線程的名稱。 請告訴我為什么會發生這種情況...

每個線程都獨立運行。 他們所做的只是數到 5 並打印WINNER ,他們不知道其他線程在做什么,或者是否有任何線程在它們之前“獲勝”。 如果您只想讓一個線程成為贏家,那么他們需要共享某種狀態,以便他們知道哪一個是贏家。

......我該如何糾正它?

我認為@luk2302 的答案,使用共享的AtomicBoolean是解決問題的好方法。 單個AtomicBoolean由主線程創建並傳遞給所有子線程。

final AtomicBoolean raceFinished = new AtomicBoolean(false);
Threading t1 = new Threading(raceFinished);
Threading t2 = new Threading(raceFinished);
Threading t3 = new Threading(raceFinished);

然后當每個線程運行到循環結束時,只有一個線程能夠將AtomicBoolean設置為 true 並聲明自己是贏家。

for (int i = 0; i < 5; i++) {
    // ...
}
// i == 5 here
// this is an atomic operation and will succeed only for 1 thread
if (raceFinished.compareAndSet(false, true)) {
    // this is only printed if raceFinished was false beforehand
    System.out.println("WINNER IS  " + Thread.currentThread().getName());
}

這是如何運作的? 單個AtomicBoolean在所有線程之間共享。 它內部是一個volatile boolean字段和邏輯,以確保對布爾值進行原子更新。 volatile設置了內存屏障,以便線程可以適當地查看和更新​​共享布爾字段。 這很重要的原因是因為線程程序的性能嚴重依賴本地 CPU 緩存,因此它們可以獨立運行並獲得高性能。

希望這可以幫助。

暫無
暫無

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

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