7
votes

Comprendre java attendre et notifier les méthodes

J'ai un programme suivant:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class SimpleWaitNotify implements Runnable {

final static Object obj = new Object();
static boolean value = true;

public synchronized void flag()  {
    System.out.println("Before Wait");
    try {
        obj.wait();
    } catch (InterruptedException e) {
        System.out.println("Thread interrupted");
    }
    System.out.println("After Being Notified");
}

public synchronized void unflag() {
    System.out.println("Before Notify All");
    obj.notifyAll();
    System.out.println("After Notify All Method Call");
}

public void run() {
    if (value) {
        flag();
    } else {
        unflag();
    }
}

public static void main(String[] args) throws InterruptedException {
    ExecutorService pool = Executors.newFixedThreadPool(4);
    SimpleWaitNotify sWait = new SimpleWaitNotify();
    pool.execute(sWait);
    SimpleWaitNotify.value = false;
    SimpleWaitNotify sNotify = new SimpleWaitNotify();
    pool.execute(sNotify);
    pool.shutdown();

}


0 commentaires

3 Réponses :


12
votes

Vous appelez attendre code> et notifier code> sur obj code>, mais vous synchronisez sur ceci code> (car Vous avez des méthodes synchronisées).

Afin d'attendre ou de notifier, vous devez «posséder» le moniteur d'abord. Signalez les méthodes et synchronisez-la à la place: P>

public void flag()  {
    System.out.println("Before Wait");
    synchronized (obj) {
        try {
            obj.wait();
        } catch (InterruptedException e) {
            System.out.println("Thread interrupted");
        }
    }
    System.out.println("After Being Notified");
}

public void unflag() {
    System.out.println("Before Notify All");
    synchronized (obj) {
        obj.notifyAll();
    }
    System.out.println("After Notify All Method Call");
}


2 commentaires

Super. Peut faire la même chose à se débarrasser de l'objet composite obj complètement?


@MADDY: Vous devriez être capable d'attendre et de notifier sur "Ceci" - mais c'est généralement une mauvaise idée, car "ceci" est généralement une référence que l'autre code a accès, efficacement. Garder une référence privée à un objet que seul votre code sait que votre code est une bonne pratique.



3
votes

soit synchroniser code> sur obj code> ou appelez attendre code> et notifier code> sur Ça code> . Le thread d'appel doit contenir le moniteur de l'objet même em> sur lequel ces méthodes sont appelées.

Par exemple, P>

class SimpleWaitNotify implements Runnable {

  private final Object lock;
  private final boolean wait;

  SimpleWaitNotify(Object lock, boolean wait) {
    this.lock = lock;
    this.wait = wait;
  }

  public void flag()  {
    synchronized (lock) {
      System.out.println("Before Wait");
      try {
        lock.wait();
        System.out.println("After Being Notified");
      } catch (InterruptedException ex) {
        System.out.println("Thread interrupted");
      }
    }
  }

  public void unflag() {
    synchronized(lock) {
      System.out.println("Before Notify All");
      lock.notifyAll();
      System.out.println("After Notify All Method Call");
    }
  }

  public void run() {
    if (wait) {
      flag();
    } else {
      unflag();
    }
  }

  public static void main(String[] argv) throws Exception {
    ExecutorService pool = Executors.newFixedThreadPool(4);
    Object shared = new Object();
    SimpleWaitNotify sWait = new SimpleWaitNotify(shared, true);
    pool.execute(sWait);
    SimpleWaitNotify sNotify = new SimpleWaitNotify(shared, false);
    pool.execute(sNotify);
    pool.shutdown();
  }

}


1 commentaires

J'ai changé plutôt pour attendre l'objet simple de l'accès lui-même. Cependant, dans ce cas, le programme ne s'arrête pas. Le fil suspendu n'est plutôt pas notifié. Je reçois l'imprimé suivant. Avant d'attendre avant de notifier tout après notifier tout appel de méthode



1
votes

Plutôt mettre l'énoncé direct piscine.shutdown () code>, essayez comme ci-dessous.

while (!service.isTerminated())
{
    service.shutdown();
}


0 commentaires