Java等待/通知不起作用

时间:2013-10-22 17:30:59

标签: java wait notify

所以我一直在使用Java中的简单等待/通知示例,由于某种原因,我无法让它正常运行。如果有人能够看到可能是什么问题,我将非常感激!

public class ThreadDemonstration
{
private String str = null;

Thread stringCreator = new Thread(new Runnable()
{
    public void run()
    {           
        synchronized(this)
        {               
            str = "I have text";
            notify();            
        }
    }
});

private Thread stringUser = new Thread(new Runnable()
{
    public void run()
    {
        synchronized(this)
        {
            if(str == null)
            {                   
                try {
                    System.out.println("str is null, I need help from stringCreator");
                    wait();
                    System.out.println(str);
                }
                catch (InterruptedException e) 
                {
                    e.printStackTrace();
                }
            }

        }
    }
});

public static void main (String [] args)
{
    ThreadDemonstration td = new ThreadDemonstration();
    td.stringUser.start();
    td.stringCreator.start();
}

}

我目前的输出是: str为null,我需要来自stringCreator的帮助

所以由于某种原因线程stringCreator没有唤醒stringUser或我完全错过了其他东西?

谢谢!

3 个答案:

答案 0 :(得分:4)

您的块在不同对象上synchronized。它们应该synchronized超过一个公共对象,例如下面的monitor对象:

public class ThreadDemonstration
{
private String str = null;
    private final Object monitor = new Object();

Thread stringCreator = new Thread(new Runnable()
{
    public void run()
    {           
        synchronized(monitor)
        {               
            str = "I have text";
            monitor.notify();            
        }
    }
});

private Thread stringUser = new Thread(new Runnable()
{
    public void run()
    {
        synchronized(monitor)
        {
            while(str == null) //changed from if to while. This allows you to wait again if the thread gets woken up by something other than the appropriate notify.
            {                   
                try {
                    System.out.println("str is null, I need help from stringCreator");
                    monitor.wait();
                    //removed print statement from here
                }
                catch (InterruptedException e) 
                {
                    e.printStackTrace();
                }
            }
            System.out.println(str); //added print statement here. str is guaranteed to not be null here.
        }
    }
});

为了避免为同步创建单独的对象,您可以使用synchronized(ThreadDemonstration.this)synchronized(ThreadDemonstration.class)作为示例。

答案 1 :(得分:1)

试试这个:

private Thread stringUser = new Thread(new Runnable() {
    //-----

    System.out.println("str is null, I need help from stringCreator");
    notify();
    wait(100);
    System.out.println(str);

    //----
});

答案 2 :(得分:0)

您需要使用同一实例的waitnotify才能使其正常工作。由于您创建了两个不同的对象(Runnable的2个实例),因此无效。我编写了一个使用两个不同类的简单示例,使用主类的实例作为内部锁。你也可以为我们设置一个“虚拟对象”(Object lock = new Object)。

public class ThreadDemonstration {

    private static String text;

    public ThreadDemonstration(){
        Thread user = new Thread(new StringUser(this));
        Thread creator = new Thread(new StringCreator(this));
        user.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        creator.start();
    }

    public class StringCreator implements Runnable{

        private Object lock;

        StringCreator(Object lock){
            this.lock = lock;
        }

        @Override
        public void run() {
            synchronized(lock){
                text = "Yeeeehaaaaa";
                lock.notify();
            }

        }

    }

    public class StringUser implements Runnable{

        private Object lock;

        StringUser(Object lock){
            this.lock = lock;
        }

        @Override
        public void run() {

            synchronized(lock){

                if((text == null)){
                    System.out.println("I need help!");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(text);
            }

        }

    }

    public static void main(String[] args){
        new ThreadDemonstration();
    }

}