Pergunta

So I have been working on a simple wait/notify example in Java and for some reason I have not been able to get it to run properly. If anyone is able to see what might be the issue It would be very appreciated!

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

}

My current output is: str is null, I need help from stringCreator

So for some reason the thread stringCreator does not wake up the stringUser or am I missing something else entirely?

Thank you!

Foi útil?

Solução

Your blocks are synchronized over different objects. They should be synchronized over a common object, for example the monitor object below:

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

In order to avoid creating a separate object for synchronization, you can use synchronized(ThreadDemonstration.this) or synchronized(ThreadDemonstration.class) for example.

Outras dicas

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

    //----
});

You need to use the wait and notify of the same instance in order for it to work. Since you create two different objects (2 instances of Runnable) it will not work. I've written a simple example using two different classes using the main class' instance for the intrinsic lock. You could also us a 'dummy object' (Object lock = new Object) for this.

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

}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top