2016-06-06 6 views
0

Ich möchte meine gerade ungerade Zahl in der Reihenfolge 1 2 3 4 5 6 drucken. Ich denke zuerst Anruf in Odd-Thread benachrichtigen sollte die even-Thread wait() zum Drucken der nächsten geraden Zahl entsperren, aber es ist nicht der Fall. Es wird nur "1" gedrucktWarum notify() funktioniert nicht in der unteren Code?

class T1 extends Thread { 
    private String[] s1; 
    private boolean flag; 

    public T1(String[] args, boolean flag) { 
     this.flag = flag; 
     this.s1 = args; 
    } 

    public synchronized void run() { 
     for (int i = 0; i < s1.length; i++) { 
      if(flag) 
      { 
       try { 
        wait(); 
       } catch (InterruptedException e) { 
        System.out.println("exception"); 
       } 
      } 
      System.out.println(s1[i]); 
      notify(); 
      flag = true; 
     } 
    } 
} 

public class TestThread { 
    public static void main(String[] args) { 
     String[] s1 = { "1", "3", "5" }; 
     String[] s2 = { "2", "4", "6" }; 

     Runnable odd = new T1(s1,false); 
     Runnable even = new T1(s2,true); 

     new Thread(even,"even-thread ").start(); 
     new Thread(odd,"odd-thread ").start(); 

    } 
} 
+3

Sie haben zwei 'Thread' Objekte, sie signalisieren einander nicht, sie sind sich selbst signalisieren. Verwenden Sie ein gemeinsames Objekt. Nie 'notify' oder' wait' auf 'Thread'-Instanzen. –

+0

Willkommen bei StackOverflow. Bitte besuchen Sie die [Hilfe] und lesen Sie [fragen]. Haben Sie Ihren Code in Ihrem IDE-Debugger durchgegangen? Das ist der Ort, um anzufangen. –

Antwort

2

Ihre Threads melden sich selbst, anstatt den anderen Thread zu benachrichtigen.

Sie können dies beheben, indem Sie den anderen Thread nach der Synchronisierung auf seinem Monitor benachrichtigen. Es wäre jedoch besser, wait() und notify() auf einem gemeinsamen Object.

3

Wie andere darauf hinweisen, verwenden die zwei Threads unterschiedliche Monitore, sie sollten ein gemeinsames Objekt als Monitor verwenden.

Aber auch das Fixieren löst nicht alle Ihre Probleme. Wie es ist, sehe ich auch die Möglichkeit für ein verpasstes Signal. (Ein Thread kann notify aufrufen, wenn der andere nicht wartet).

Alles in allem betrachten Sie nicht einige der Richtlinien, die für Wait-Notify verwendet werden sollten.

Von Java Concurrency in Practice:

Wenn Bedingung wartet mit (Object.wait oder Condition.await):

  • immer eine Bedingung Prädikats einige haben Test von Objektzustand, bevor Sie fortfahren halten müssen ;
  • Testen Sie das Bedingungsprädikat immer vor dem Aufruf wait, und erneut nach der Rückkehr von wait;
  • Rufen Sie immer wait in einer Schleife;
  • Stellen Sie sicher, dass die Statusvariablen, aus denen das Prädikat der Bedingung besteht, von der Sperre geschützt werden, die der Bedingungswarteschlange zugeordnet ist.
  • Halten Sie die Sperre, die mit der Bedingungswarteschlange verknüpft ist, wenn Sie wait, notify oder notifyAll aufrufen; und
  • Lassen Sie die Sperre nicht los, nachdem Sie das Prädikat der Bedingung überprüft haben, aber bevor Sie darauf reagieren.
+1

Eine weitere gute Ressource, die die Noobs kostenlos lesen können, ist der Abschnitt "Geschützte Blöcke" in den Oracle Java-Lernprogrammen: https://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html –

+1

@WarrenDew Berücksichtigen Sie diese Planung: Der ungerade Thread wird zuerst in den synchronisierten Block geladen, die Benachrichtigung wird notiert (keine Threads warten), und das Flag wird auf "true" gesetzt. Anschließend wird die zweite Schleife aufgerufen und es wird mit dem Warten begonnen. Dann kann der even thread in den synchronisierten Block gelangen, das Flag ist true und es beginnt zu warten. Doch es hat das Signal verpasst, auf das es warten sollte. Jetzt warten beide Threads auf ein Signal, das niemals kommen wird. – bowmore

+0

Sie haben Recht, ich habe nur den stationären Zustand und nicht beim Start betrachtet. Guter Punkt. –

0

Sie können den Code wie folgt benötigen:

class MyThread extends Thread { 
    private Object object; 
    private String[] s1; 

    public MyThread(String[] args, Object object) { 
     this.object = object; 
     this.s1 = args; 
    } 

    public void run() { 
     synchronized (object) { 
      for (int i = 0; i < s1.length; i++) { 
       System.out.println(s1[i]); 
       object.notifyAll(); 
       if (i == s1.length - 1) return; 
       try { 
        object.wait(); 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    } 
} 

public class TestThread { 
    private static Object object = new Object(); 

    public static void main(String[] args) { 
     String[] s1 = { "1", "3", "5" }; 
     String[] s2 = { "2", "4", "6" }; 
     Thread odd = new MyThread(s1, object); 
     odd.start(); 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     Thread even = new MyThread(s2, object); 
     even.start(); 
    } 
} 

der Ausgang ist:

1 
2 
3 
4 
5 
6 
Verwandte Themen