通知不让线程退出等待状态

时间:2013-10-06 07:17:21

标签: java multithreading

我正在尝试使用2个线程。 1个线程只打印奇数,另一个线程只打印偶数,它必须是一个替代操作。

例如:

Thread1 1
Thread2 2
Thread1 3
Thread2 4
and so on..

以下是程序,请告诉我出错的地方,因为即使thread2正在通知它,thread1也没有退出等待状态..

    public class ThreadInteraction {

    public static void main(String[] args) {
        new ThreadInteraction().test();
    }

    private void test() {
        ThreadA ta = new ThreadA();
        Thread t = new Thread(ta);
        t.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        for(int i=2;i<=50;){
            System.out.println("Thread2 "+i);
            synchronized (t) {
                try {
                    t.notify(); 
                    t.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            i=i+2;
        }
    }
}

    class ThreadA implements Runnable{
        @Override
        public void run() {
            for(int i=1;i<50;){
                System.out.println("Thread1 "+i);
                synchronized (this) {
                        try {
                            notify();                           
                            wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                }
                i=i+2;
            }
        }
    }

3 个答案:

答案 0 :(得分:2)

问题是,在一种情况下,您正在锁定Thread t [synchronized(t)],而在其他情况下,您正在锁定TheadA对象本身[synchronized(this)]。

如果你想让线程相互通信,那么两者都应该锁定同一个对象,然后wait notify将按预期工作。

编辑:

您的程序中还有另一个问题,您没有使用任何变量来协调2个线程。所以你可能会看到这样的输出2,1,4,3 ......等等。点是线程交替工作但不按顺序工作。 所以你应该在2个线程之间共享一个应该递增的变量。 第二个问题是你没有处理虚假的唤醒调用[阅读一些关于此的文档],你应该总是等待一段时间内调用。

答案 1 :(得分:0)

根据Lokesh提供的答案修改我的代码

public class ThreadInteraction {
    public static void main(String[] args) {
        new ThreadInteraction().test();
    }
    private void test() {
        ThreadA ta = new ThreadA();
        Thread t = new Thread(ta);
        t.start();

        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }

        for(int i=2;i<=50;){
            System.out.println("Thread2 "+i);
            synchronized (ta) {
                try {
                    ta.notify();    
                    ta.wait();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            i=i+2;
        }
    }
}
class ThreadA implements Runnable{
    @Override
    public void run() {
        for(int i=1;i<50;){
            System.out.println("Thread1 "+i);
            synchronized (this) {
                    try {
                        notify();                           
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
            i=i+2;
        }
    }
}

答案 2 :(得分:0)

你真的混淆了线程和锁。我建议您创建一个且只有一个用于锁定的对象,因为您似乎并不清楚自己锁定了什么。

如果您通知()并且没有任何内容正在侦听,则信号将丢失。但是,wait()可以虚假地唤醒。

因此,notify()应该伴随状态更改,而wait()应该在循环中检查更改。