2017-05-08 1 views
-2

Le code suivant n'obtient pas notifier le lecteur de threads il exécute le programme d'écriture, puis se termine. Pourquoi est-ce comme ça? Le notifyall doit réveiller tous les threads qui sont à l'état d'attente.Mon thread ne reçoit pas de notification et mon programme se bloque

public class Testing { 

    public static void main(String[] args) { 
     Testing testing=new Testing(); 
     testing.reader.start(); 
     testing.writer.start(); 
    } 
    Thread reader = new Thread("reader") { 
     public void run() { 

      System.out.println("reader started"); 

      synchronized (this) { 
       try { 

        wait(); 
       } catch (InterruptedException ex) { 
        ex.printStackTrace(); 
       } 
      } 
      for (int i = 0; i < 10; i++) { 
       System.out.println("reader " + i); 

      } 
     } 

    }; 
    Thread writer = new Thread("writer") { 
     public void run() { 
      System.out.println("writer started"); 

      for (int i = 0; i < 10; i++) { 
       System.out.println("writer " + i); 
      } 
      synchronized (Thread.currentThread()) { 
       notifyAll(); 
      } 

     } 

    }; 

} 
+0

oui le fil de lecture est retourné tout en appelant thread.But courant ni le notifier et notifier ne réveille pas le fil d'attente. –

+0

oups! C'était une erreur.Je vais corriger cela à l'écrivain.En fait maintenant le fil de discussion actuel est écrivain.Pouvez-vous m'aider à comprendre comment puis-je notifier le fil du lecteur. –

+0

Ne jamais appeler 'wait' sans avoir d'abord confirmé, à l'intérieur du bloc' synchronized', que la chose que vous attendez n'est pas déjà arrivée. Et ne quittez jamais le bloc 'synchronized' après avoir appelé' wait' sans avoir confirmé que la chose que vous attendez est arrivée. (De plus, votre script appelle 'notifyAll' sans avoir rien changé dans le bloc' synchronized', donc il n'y a rien à signaler.) –

Répondre

0

notifyAll() ne fait pas partie de la classe Thread, mais appartient à la classe de base de l'objet, dans l'auteur de fil, notifyAll() est la fonction de l'écrivain objet, il peut
réveiller le fil qui a l'écrivain Verrouillage d'objet; enter image description here

+0

alors comment puis-je notifier le thread du lecteur à partir du thread de l'auteur. –

0

Le code suivant ne soit pas informer le lecteur de fil il exécute l'écrivain puis se termine. Pourquoi est-ce comme ça?

Votre programme ne se termine pas parce que le thread d'écriture se termine, mais le fil du lecteur est coincé dans wait(). Le problème avec votre code est que le thread du lecteur attend son propre objet thread alors que le thread écrivain notifie sur son propre objet thread qui est différent. Ce que vous devez faire est d'avoir chacun d'eux attendre et notifier sur le même instance d'objet.

Une solution rapide serait d'utiliser un objet de verrouillage statique:

private static final Object lockObject = new Object(); 
// reader: 
synchronized (lockObject) { 
    lockObject.wait(); 
... 
// writer 
synchronized (lockObject) { 
    lockObject.notify(); 

Puis le lecteur et l'écrivain sont le verrouillage, l'attente, et notifier-ment sur la même dernière instance d'objet. C'est un bon motif pour synchroniser sur les champs qui ne peuvent pas être modifiés, donc private final Object ou un tel est le meilleur. En outre, vous avez seulement un fil de sorte que notify() est suffisant.

Toutefois, votre code souffre toujours de problèmes de condition de concurrence. Il est possible (quoique improbable) pour votre écrivain d'appeler notifyAll()avant le lecteur obtient le wait(). Si la notification se produit et qu'il n'y a personne en attente, alors c'est un noop et le lecteur se bloque quand il arrive au wait().

Une meilleure solution serait d'utiliser une commune AtomicBoolean:

private final AtomicBoolean writerDone = new AtomicBoolean(); 
... 
// reader 
while (!writerDone.get()) { 
    synchronized (writerDone) { 
     writerDone.wait(); 
    } 
} 
// writer 
writerDone.set(true); 
synchronized (writerDone) { 
    writerDone.notifyAll(); 
} 
0

vous venez de faire peu de changement, comme suit:

public static void threadTest(){ 
     Test testing = new Test(); 
     testing.lock = new Object(); 
     testing.reader.start(); 
     testing.writer.start(); 
    } 
    private Object lock; 
    Thread reader = new Thread("reader") { 
     public void run() { 

      System.out.println("reader started"); 

      synchronized (lock) { 
       try { 
        lock.wait(); 
       } catch (InterruptedException ex) { 
        ex.printStackTrace(); 
       } 
      } 
      for (int i = 0; i < 10; i++) { 
       System.out.println("reader " + i); 

      } 
     } 

    }; 
    Thread writer = new Thread("writer") { 
     public void run() { 
      System.out.println("writer started"); 

      for (int i = 0; i < 10; i++) { 
       System.out.println("writer " + i); 
      } 
      synchronized (lock) { 
       lock.notifyAll(); 
      } 

     } 

    }; 
+0

merci qui a aidé. :) –