2016-03-19 7 views
0

Ich habe eine Methode, die von einem run() aufgerufen wird Threads übergeben. Ich mache einen Iterator für die Berechnung, wie viele Threads übergeben werden, und dies für Warte als Bedingung verwenden()notifyAll wacht nicht Thread

Ich habe den folgenden Code, die von den Threads ausgeführt wird ausgeführt()


public void testMethod(Object x) throws InterruptedException { 
    synchronized (x) { 
     while(threadsWaiting <= 5) { 
      threadsWaiting++; 
      System.out.println(x.getName() + " waiting " + 
        " | Threads waiting: " + threadsWaiting); 
      x.wait(); 
     } 
     x.notifyAll(); 
     System.out.println(x.getName() + " passed " + 
       " | Threads waiting: " + threadsWaiting); 
    } 
} 

Beispiel Ausgabe:

Thread 0 is created 
Thread 1 is created 
Thread 2 is created 
Thread 3 is created 
Thread 4 is created 
Thread 5 is created 
Thread 6 is created 
Thread 7 is created 
Thread 8 is created 
Thread 9 is created 
Thread 10 is created 
Thread 11 is created 
Thread 12 is created 
Thread 13 is created 
Thread 14 is created 
Thread 15 is created 
Thread 16 is created 
Thread 17 is created 
Thread 18 is created 
Thread 19 is created 
Thread 20 is created 
Thread 16 waiting | Threads waiting: 1 
Thread 9 waiting | Threads waiting: 2 
Thread 5 waiting | Threads waiting: 3 
Thread 14 waiting | Threads waiting: 4 
Thread 0 waiting | Threads waiting: 5 
Thread 13 waiting | Threads waiting: 6 
Thread 15 passed | Threads waiting: 6 
Thread 10 passed | Threads waiting: 6 
Thread 4 passed | Threads waiting: 6 
Thread 12 passed | Threads waiting: 6 
Thread 1 passed | Threads waiting: 6 
Thread 20 passed | Threads waiting: 6 
Thread 11 passed | Threads waiting: 6 
Thread 18 passed | Threads waiting: 6 
Thread 3 passed | Threads waiting: 6 
Thread 2 passed | Threads waiting: 6 
Thread 17 passed | Threads waiting: 6 
Thread 8 passed | Threads waiting: 6 
Thread 6 passed | Threads waiting: 6 
Thread 19 passed | Threads waiting: 6 
Thread 7 passed | Threads waiting: 6 

Wie Sie alle Fäden sehen können, die nicht passieren warten.

Dies funktioniert nur auf folgende Weise: Ich übergebe 10 x Objekte. 5 von ihnen gehen zu warten(), die anderen 5 drucken. Nach dem Drucken wird x.notifyAll() aufgerufen, aber nicht mehr 'Finished' wird gedruckt.

Warum sind sie im Leerlauf, nachdem ich notifyAll() aufgerufen habe? Ich weiß, dass sie frei sind, weil Finished nur 5 Mal gedruckt wird, auch nachdem ich notifyAll() aufrufen

+0

Kann das Problem nicht reproduzieren. Ich bekomme 5 'Waiting' und 10' Finished' in meiner IDE und in [ideone] (http://ideone.com/ODvI0w). – Nier

+0

Ist Ihr x alle ** Instanzen ** in jedem Thread? Weil, wenn ich mein x von statisch zu nicht-statisch ändere, bekomme ich 5 'Waiting' und 5' Finished', wie du in deiner Frage erwähnt hast. – Nier

+0

@Nier Ja, sie sind alle verschiedene Instanzen in jedem Thread, wie ich es übergeben wie 'ClassName.method (this);' innerhalb 'run()' 'method' ist die Methode, die in meiner Frage ist und' this' ist x –

Antwort

0

Vollarbeitsbeispiel 10 Threads erstellen, warten, wenn der Thread-ID mehr als 5.

public class Notify { 

    public static void main(String[] args) { 
     Object obj = new Object(); 
     for (int i = 1; i <= 10; i++) { 
      Runnable myThread = new MyThread(i, obj); 
      new Thread(myThread).start(); 
     } 
    } 

    public static class MyThread implements Runnable{ 

     static final int MAX_THREAD = 5; 
     int id; 

     Object x; 

     public MyThread(int id, Object x) { 
      this.id = id; 
      this.x = x; 
     } 

     @Override 
     public void run() { 
      if(id > MAX_THREAD){ 
       try { 
        synchronized (x) { 
         x.wait();      
        } 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
      //Process something 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println("Process Thread : " + id); 
      synchronized (x) { 
       x.notifyAll();    
      } 
     } 

    } 

} 
+0

Ich mache genau das gleiche ... Ich habe eine synchronisierte x.wait() und später mache ich x.notifyAll, aber es ist nicht synchronisiert, und selbst wenn es war es macht keinen Unterschied, versuchte ich . Der einzige Unterschied ist, dass Sie all dies in run() tun, während ich run() zu einer anderen Methode gehe, um eine Instanz von sich selbst (this) zu übergeben, die das Objekt x ist. Aber das ist genau dasselbe. Warum sollte meine Arbeit nicht funktionieren? –

+0

Wie genau starten Sie Ihre Threads? –

+0

@GordonFreemanTurtle Wenn Sie "this" als Objekt x übergeben, handelt es sich um alle verschiedenen Instanzen, die Ihre synchronisierte auf verschiedenen Monitoren sperrt. Überlegen Sie stattdessen this.getClass() '. – Nier

0

ist es möglich, dass notifyAll wird aufgerufen, bevor alle anderen Threads wait aufgerufen haben. Wenn dies geschieht, warten die anderen Threads auf dem Monitor, bis sie erneut benachrichtigt werden.

Anstatt zu warten und zu benachrichtigen, sollten Sie etwas in java.util.concurrent suchen. Ich würde mit einem CountDownLatch beginnen.

+0

Wie können Threads 'x.notifyAll()' aufrufen, bevor andere Threads 'x.wait() 'aufrufen? Sie befinden sich alle im "synchronisierten" Block. – Nier

+0

Einige der Threads beginnen möglicherweise nicht einmal, bevor die anderen fertig sind. Auch nicht klar, was mit Ihrer Zählvariablen vor sich geht. Ist das eine Art von geteilter Variable zwischen den Threads? – Bill

+0

@Bill Ich habe die Frage aktualisiert. Ich benutze es, um zu bestimmen, wann ich aufhören soll, Threads warten zu lassen. –

0
while(threadsWaiting <= 5) { 
     threadsWaiting++; 
     System.out.println(x.getName() + " waiting " + 
       " | Threads waiting: " + threadsWaiting); 
     x.wait(); 
    } 

Say threadsWaiting ist 4. Wir passieren den <= 5 Test, also geben wir die while Schleife. Wir erhöhen threadsWaiting auf 5 und rufen dann wait an. Aber wir warten auf threadsWaiting, um 5 oder mehr zu sein, und es ist bereits. Wir warten also auf etwas, das bereits passiert ist.

Warten auf etwas, was bereits passiert ist, ist der häufigste Missbrauch von notify/wait.

+0

Warum warten Sie, bis 'threadsWaiting' 5 oder mehr ist? Ich will, dass diese Threads auf "notify" warten, ich brauche keine Threads mehr zu machen "wait" –

+0

@GordonFreemanTurtle Ich verstehe nicht, was du sagst. Auf welche Bedingung sollten die Threads warten? –

+0

Da sie warteten, möchte ich, dass sie mit der Methode fortfahren und die print-Anweisung erreichen, die nach 'x.notifyAll()' steht, wenn sie wieder aufgenommen werden. –

Verwandte Themen