NotifyAll不起作用

时间:2018-08-03 18:28:19

标签: java multithreading notify

此代码从两个不同的线程打印偶数/奇数。在这里,我的程序卡在wait()中,无法使用notifyAll()唤醒睡眠线程。

想知道,为什么notifyAll无法唤醒所有睡眠的线程? 需要知道我在这里做错了。

class EvenOddThread {
  public static void main (String [] args) {
  Runnable runnEven = new ThreadPrint (true, 10);
  Runnable runnOdd = new ThreadPrint (false, 10);

  Thread t1 = new Thread (runnEven);
  Thread t2 = new Thread (runnOdd);

  t1.start ();
  t2.start ();
  }
}

class ThreadPrint implements Runnable {
  private boolean isEvenPrint = false;
  private int maxPoint = 0;
  ThreadPrint (boolean isEven, int max) {
    isEvenPrint = isEven;
    maxPoint = max;
  }

  @Override
  public void run () {
    Print p = new Print();
    if (isEvenPrint)
      p.printEven(maxPoint);
    else
      p.printOdd(maxPoint);
  }
}

class Print {


  public synchronized void printEven (int maxPoint) {
    int even = 0;
    while (even <= maxPoint) {
      System.out.println(even);
      even = even + 2;
      try {
      wait();
    }
    catch (Exception e) {
      System.out.println(e);
    }

    notifyAll();
    }
  }

  public synchronized void printOdd (int maxPoint) {
    int odd = 1;
    while (odd <= maxPoint) {


    System.out.println(odd);
    odd = odd + 2;
    try {
      wait();
    }
    catch (Exception e) {
      System.out.println(e);
    }

      notifyAll();
    }
  }
}

谢谢, 湿婆

4 个答案:

答案 0 :(得分:3)

两个线程在打印第一个数字后都输入wait。由于两个线程都已暂停,因此任何一个线程都无法唤醒另一个线程。

为了使一对线程以这种方式交替,您可以具有控制每个线程进度的单独条件。每个线程在完成自己的工作单元后将取消阻塞另一个线程。可以使用SemaphoreCyclicBarrierPhaser来完成。

答案 1 :(得分:1)

notifyAll()应该通知所有在特定对象上等待的线程,而不是所有在任何地方等待的线程。您要做的是,为每个线程创建一个Print实例-然后使用非限定的wait()和notifyAll()-这意味着您的线程使用每个线程本地的变量进行通信。

因此,首先您必须使它们使用相同的同步/信号对象。

第二,至少需要提供一些初始踢。请务必小心,因为当您确定其中至少有一个已经在收听时,您需要发出此信号。最好的情况是确保他们俩都在听,这样您就可以避免无数种可能的种族状况。

= rant = Sun在这里通过隐藏程序员的(互斥量,条件,信号)三合会而使IMO陷入困境,这很可能是为了简化多线程。他们失败了。 = / rant =

答案 2 :(得分:1)

似乎您只希望两个线程以乒乓方式打印奇/偶数。然后,您可以使用ReentrantLock。有几种方法可以做到这一点。

I。锁

public static final ReentrantLock lock = new ReentrantLock();
public static final int LIMIT = 50;
public static int toPrint = 0;

public static void main(String[] args){
    Thread t1 = new Thread(() -> {
        while (true){
            try {
                lock.lock();
                if(toPrint > LIMIT) break;
                else if(toPrint % 2 == 0) {
                    System.out.println(toPrint++);
                }
            } finally {
                lock.unlock();
            }
        }
    });

    Thread t2 = new Thread(() -> {
        while (true) {
            try {
                lock.lock();
                if (toPrint > LIMIT) break;
                else if (toPrint % 2 == 1) {
                    System.out.println(toPrint++);
                }
            } finally {
                lock.unlock();
            }
        }
    });
    t1.start();
    t2.start();
}

II。易挥发 (易碎,但有效)

public static final int LIMIT = 50;
public static volatile int toPrint = 0;

public static void main(String[] args){
    Thread t1 = new Thread(() -> {
        while (true){
            int cur = toPrint;
            if(cur > LIMIT) break;
            else if(cur % 2 == 0){
                System.out.println(cur);
                toPrint = cur + 1;
            }
        }
    });

    Thread t2 = new Thread(() -> {
        while (true) {
            int cur = toPrint;
            if(cur > LIMIT) break;
            else if(cur % 2 == 1){
                System.out.println(cur);
                toPrint = cur + 1;
            }
        }
    });
    t1.start();
    t2.start();
}

答案 3 :(得分:0)

class EvenOddThread {
  public static void main (String [] args) {
  Runnable runnEven = new ThreadPrint (10);

  Thread t1 = new Thread (runnEven);
  Thread t2 = new Thread (runnEven);

  t1.start ();
  t2.start ();

  }
}

class ThreadPrint implements Runnable {
  private int maxPoint = 0;
  private int counter = 0;
  ThreadPrint (int max) {
    maxPoint = max;
  }

  @Override
  public void run () {
    while (counter <= maxPoint) {
      synchronized(this) {
        if (counter % 2 == 0) {

          System.out.println("By Thread" + Thread.currentThread().getName() +" :: "+ counter);
          counter ++;
          notify();
          try {
            wait();
          }
          catch (Exception e) {
            System.out.println(e);
          }
        }
        else if (counter % 2 != 0){
          System.out.println("By Thread" + Thread.currentThread().getName() +" :: "+ counter);
          counter ++;
          notify();
          try {
            wait();
          }
          catch (Exception e) {
            System.out.println(e);
          }
        }
      }
    }
  }
}

谢谢大家的回答,但我得到了 here找出我该怎么做才能更正我的代码。

现在,它以我想要的方式工作。 :)