为什么notify()不能在下面的代码中工作?

时间:2016-06-06 21:51:00

标签: java multithreading

我想按顺序打印我的奇数偶数1 2 3 4 5 6.我认为首先在奇数线程中通知调用应该解除阻塞偶数线程的wait()以打印下一个偶数,但事实并非如此。它只打印“1”

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 个答案:

答案 0 :(得分:3)

正如其他人指出的那样,两个线程使用不同的监视器,他们应该使用共享对象作为监视器。

然而,即使修复也无法解决所有问题。因为它是我也看到错过信号的机会。 (当另一个线程没有等待时,一个线程可以调用notify)。

总而言之,您不会考虑应该用于wait-notify的一些准则。

来自实践中的Java并发

  

使用条件等待(Object.waitCondition.await)时:

     
      
  • 始终有一个条件谓词 - 对象状态的一些测试,必须在继续之前保持;
  •   
  • 始终在调用wait之前测试条件谓词,并在从wait返回后再次测试;
  •   
  • 始终在循环中调用wait;
  •   
  • 确保构成条件谓词的状态变量由与条件队列关联的锁保护;
  •   
  • 调用waitnotifynotifyAll时,保持与条件队列关联的锁定;和
  •   
  • 检查条件谓词后但在采取行动之前不要释放锁定。
  •   

答案 1 :(得分:2)

你的线程正在通知自己,而不是通知另一个线程。

您可以通过在其监视器上同步后通知另一个线程来解决此问题。但是,对于共享wait()上的notify()Object会更好。

答案 2 :(得分:0)

您可能需要这样的代码:

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();
    }
}

输出是:

1
2
3
4
5
6