2017-01-21 47 views
-1
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米時打印所有線程的名稱。請告訴我爲什麼會發生這種情況,我該如何糾正它?無法使用break語句退出for循環

+3

每個線程都會獨立運行*其他線程。當一個人從中斷時,其他人不受影響。 –

+0

感謝您的回答。你能告訴我如何停止當前代碼中的線程? @JohnBollinger –

+0

也許使用'AtomicBoolean' – luk2302

回答

0

但什麼是與此代碼發生的是,for循環運行,直到每個線程達到15米在打印所有線程的名字,因爲他們達到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是真實的,並宣佈自己獲勝者。

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高速緩存,因此它們可以獨立運行並獲得高性能。

希望這會有所幫助。

0

如何以下列方式使用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; 
} 
+0

非常感謝幫助我。我是一個初學者,你可以指導我到一些鏈接,我可以瞭解更多關於多線程。 –

+0

@jackreacher並非如此。但我認爲多線程是一個讓你自己成爲初學者的最糟糕的概念/技術 - 幾乎其他任何東西都更有意義。 – luk2302

+1

使用'raceFinished.compareAndSet(false,true)'會更有效一些,因爲'getAndSet(...)'就是在循環中使用的。 – Gray