1

所以我一直在用 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 为空,我需要 stringCreator 的帮助

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

谢谢!

4

3 回答 3

6

您的块位于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)例如。

于 2013-10-22T17:34:20.813 回答
1

Try this :

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

    //----
});
于 2013-10-22T17:40:43.123 回答
0

您需要使用同一实例的waitandnotify才能使其工作。由于您创建了两个不同的对象( 的 2 个实例Runnable),因此它将不起作用。我编写了一个简单的示例,使用两个不同的类,使用主类的实例作为内部锁。您也可以为此使用“虚拟对象”( 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();
    }

}
于 2013-10-22T17:59:56.983 回答