2017-01-21 4 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(); 
    } 
} 

Ich möchte den Namen des Threads, der zuerst die 5 Meter erreicht und dann aus der Schleife gehen. Aber was passiert mit diesem Code ist, dass die For-Schleife läuft, bis jeder Thread 5 Meter erreicht und den Namen aller Threads druckt, wenn sie die 5 Meter erreichen. Bitte sag mir, warum passiert das und wie kann ich das korrigieren?Kann nicht für Schleife mit break-Anweisung

+3

Jeder Thread führt die Schleife * unabhängig * von den anderen. Wenn man davon bricht, sind die anderen unberührt. –

+0

Danke für die Antwort. Kannst du mir zeigen, wie ich die Threads in meinem aktuellen Code stoppen kann? @ JohnBollinger –

+0

vielleicht ein 'AtomicBoolean' verwenden – luk2302

Antwort

0

Aber was mit diesem Code geschieht, ist, dass die die for-Schleife ausgeführt wird, bis jeder Faden 5 Meter erreicht und das Drucken der Namen aller Fäden, wie sie die 5 Meter erreichen. Bitte sagen Sie mir, warum das passiert ...

Jeder der Threads läuft unabhängig voneinander. Alles, was sie tun, ist bis 5 zu zählen und WINNER zu drucken und sie haben keine Ahnung, was die anderen Threads machen oder ob irgendwelche vor ihnen "gewonnen" haben. Wenn Sie wollen nur ein Thread der Gewinner sein, dann müssen sie eine Art Staat teilen, damit sie wissen, welcher der Gewinner ist.

... und wie kann ich das korrigieren?

Ich denke @ luk2302's Antwort, mit einer gemeinsamen AtomicBoolean ist eine gute Möglichkeit, das Problem zu beheben. Eine einzige AtomicBoolean wird vom Hauptthread erstellt und an alle Unterthreads übergeben.

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

Dann, da jeder Faden an dem Ende der Schleife ausgeführt wird, nur ein Thread ist in der Lage, die AtomicBoolean einzustellen wahr zu sein und sich zum Gewinner erklärt.

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()); 
} 

Wie funktioniert das? Die einzige AtomicBoolean ist für alle Threads freigegeben. Darin befindet sich ein volatile boolean Feld und eine Logik, um atomare Aktualisierungen für den booleschen Wert zu gewährleisten. Das volatile baut Speicherbarrieren auf, damit die Threads das freigegebene boolesche Feld entsprechend anzeigen und aktualisieren können. Der Grund dafür ist, dass die Leistung von Threaded-Programmen stark von lokalen CPU-Caches abhängig ist, so dass sie unabhängig voneinander ausgeführt werden können und eine hohe Leistung erzielen.

Hoffe, das hilft.

0

Wie wäre es ein AtomicBoolean auf folgende Weise mit:

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(); 
    } 
} 

Wenn Sie die „Rasse“ nicht wollen weiter, nachdem der Sieger gefunden wurde, dann fügen Sie den folgenden am Anfang der Schleife:

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

vielen Dank für die Hilfe. Ich bin ein Anfänger kann Sie mich auf einige Links verweisen, wo ich mehr über Multithreading lernen kann. –

+0

@jackreacher Nicht wirklich. Aber ich denke, Multithreading ist das einzige schlechteste Konzept/Technik, um sich als Anfänger zu beschäftigen - fast alles andere macht mehr Sinn. – luk2302

+1

Die Verwendung von 'raceFinished.compareAndSet (false, true)' ist ein wenig effizienter, weil 'getAndSet (...)' im Hintergrund nur in einer Schleife verwendet wird. – Gray