2017-09-22 1 views
-2

Ich bin neu in Multithreading in Java. Ich versuche, ein Programm auszuführen, das mehrere "Writer" simulieren kann, die Daten als Ausgabe schreiben würden.Aufruf wait() stoppt nicht den richtigen Thread

Ich möchte die Autoren alle an einem bestimmten Punkt zu stoppen, damit ich an sie warte(), aber es funktioniert nicht. Ich weiß, wo das Problem passiert, aber ich weiß nicht, warum es passiert.

public void run() { 
    ExecutorService executor = Executors.newFixedThreadPool(nbOfWriters); 
    try { 
     // Create a list with all the writers that should run at the same time 
     Writer[] writers = new Writer[nbOfWriters]; 
     for (int i = 0; i < nbOfWriters; i++) { 
      writers[i] = new Writer(i); 
      executor.execute(writers[i]); 
     } 
     /* 
     Expected outcome: 
     start every writer -> wait 3 seconds 
     pause every writer -> wait 3 seconds 
     run every writer -> wait 3 seconds 
     end 
     */ 
     TimeUnit.SECONDS.sleep(3); 
     for (Writer writer : writers) { 
      synchronized (writer) { 
       System.out.println("HERE 1"); 
       writer.wait(); 
       System.out.println("HERE 2"); 
      } 
     } 

     TimeUnit.SECONDS.sleep(3); 
     for (Writer writer : writers) { 
      synchronized (writer) { 
       writer.notify(); 
      } 
     } 
     Thread.sleep(3); 
     // End of the test 
     for (Writer writer : writers) writer.end(); 
    } 
    catch (InterruptedException ex) { 
     System.out.println(ex.getMessage()); 
    } 
    finally { 
     try { 
      executor.shutdown(); 
      executor.awaitTermination(5, TimeUnit.SECONDS); 
     } 
     catch (InterruptedException ex) { 
      ex.getMessage(); 
     } 
     finally { 
      executor.shutdownNow(); 
     } 
    } 
} 

Die Writer schreiben nur Zeug als Ausgabe (nicht wichtig hier). Ich habe print Anweisung "HIER 1" und "HIER 2" hinzugefügt, um zu zeigen, wo das Programm fehlschlägt. Grundsätzlich wird "HIER 2" nie erreicht.

In der Theorie, was passieren soll ist, dass ich Daten als Ausgabe für 3 Sekunden, dann nichts für 3 Sekunden geschrieben, dann wieder Daten als Ausgabe geschrieben.

Die tatsächliche Ausgabe ist: Stuff wird als Ausgabe für 3 Sekunden geschrieben. "HIER 1" gedruckt. Stuff wird weiterhin als Ausgabe angezeigt, keine Pause, kein "HIER 2" und das Programm hört nie auf.

Es scheint mir wie wait() stoppt den falschen Thread.

Antwort

0

Sollte nicht writer.wait() Anruf warten im spezifischen Writer-Thread wie andere Methoden würde?

No.

Die Aussage, writer.wait(); verwendet das writer Objekt als monitor. Ein Monitor soll auf ganz bestimmte Art und Weise benutzt werden *. Es erlaubt einem Thread, auf einen (möglicherweise unbekannten) anderen Thread zu warten, um eine Aufgabe abzuschließen. Der Thread, der warten möchte, tut dies durch Aufruf o.wait();

Es gibt keine Möglichkeit für einen Thread machen einen anderen Thread eine Funktion aufrufen. Es gibt keine Möglichkeit für einen Thread einen anderen Thread überhaupt etwas zu tun. Threads tun, was der Code, den sie gerade ausführen, ihnen sagt, und in einem gut entworfenen Programm teilt ihnen dieser Code mit, miteinander zu kooperieren. Es gibt Möglichkeiten für Thread A fragen Thread B, etwas zu tun, aber es ist bis Sie den Code schreiben, der in Thread A ausgeführt wird, um die Frage zu tun, und es liegt an Ihnen, den Code zu schreiben, der in Thread ausgeführt wird B, der erkennt, wann es gefragt wird, und dann was auch immer tut.


* Siehe Oracle "guarded block" tutorial.
Hinweis! dass das Tutorial nicht das Wort "Monitor" verwendet, sondern über dasselbe Muster spricht.

0

Die Dokumentation für wait() sagen:

den aktuellen Thread Ursachen zu warten, bis ein anderer Thread die Notify() aufruft-Methode oder die notifyAll() Methode für dieses Objekt.

So ist der Haupt-Thread ist, was vor "HERE 2" wartet, und da es stecken Warte ist, kann es nie zu notify bekommen.

Ich bin mir nicht sicher, ob es explizite Möglichkeiten gibt, das zu tun, was du willst (sag einem anderen Thread, dass er warten soll). Es gibt einige veraltete APIs mit einer guten Erklärung dafür, warum sollte man sie nicht benutzen: https://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html

+0

Sollte nicht writer.wait() Aufruf im spezifischen Writer-Thread wie andere Methoden warten? – Touniouk

+0

@ Touniouk: welche "anderen Methoden" werden in einem anderen Thread als dem aufrufenden/aktuellen Thread ausgeführt? – Holger

+0

@ Touniouk Nr. Java gibt Ihnen keine Möglichkeit, einen anderen Thread zu zwingen, etwas zu unternehmen. Was Sie tun würden, ist Ihre Anfrage zu diesem anderen Thread zu kommunizieren (und hoffe, dass sie es ehren). Sie könnten dies über ein Signal oder einen Teil der geteilten Daten tun, den der andere Thread zu überprüfen weiß. –

Verwandte Themen