0

I have 2 classes. One method of the class calls the other class' method, but it has to wait until the method finishes to proceed to the execution of the rest of the code.

This is a rough code of what I'm trying to make. And I know this doesn't work.

public class Example 
{
    Thread thread;

    public Example(Thread thread)
    {
        this.thread = thread;
    }

    public void doSomethingElse()
    {
        System.out.println("Do something else");
        thread.notify();
    }
}

public class Example2 
{
    Thread thread;
    Example example;

    public Example2()
    {
        example = new Example(thread);
        thread = new Thread()
        {
            public void run()
            {
                example.doSomethingElse();
                try {
                    this.wait();
                } catch (InterruptedException ex) {                    
                }
                System.out.println("Do something");
            }
        };
    }

    public void doSomething()
    {
        thread.run();
    }
}

Now do you know how to make this right?

William Wino
  • 3,599
  • 7
  • 38
  • 61

3 Answers3

0

Couple of points :

  • you should acquire lock before calling wait or notify method. The lock must be on same object. In code you are calling wait on example2 object but calling notify on different object.
  • thread.run() means calling run method of thread object, its not creating new thread its same as example.doSomething(). When you create thread start that thread by calling start method.

Here is my implementation

    class Example implements Runnable 
    {
        public void run()
        {
            doSomething();
        }
        public void doSomething(){
            synchronized(this){
                System.out.println("Do something else");
                try{
                   Thread.sleep(1000); 
                   this.notify();    
                }catch (InterruptedException ignore) {}            
            }    
        }
    }

    class Example2 implements Runnable 
    {
        Thread thread;
        Example example;

        public Example2(Example example){
            this.example = example;
        }


        public void run(){
            doSomething();    
        }

        public void doSomething(){
            synchronized(example){
                System.out.println("waiting for example 1 to complete");
                try{
                    example.wait();    
                }catch (InterruptedException ignore) {}

            }
            System.out.println("Do something");
        }
    }

    public class Entry{
        public static void main(String[] args){

            Example example = new Example();

            Example2 obj = new Example2(example);
            Thread t = new Thread(obj);
            t.start();

            Thread t2 = new Thread(example);
            t2.start();
        }
    }

In code Thread.sleep(1000); statement is not needed.

Aniruddha
  • 3,513
  • 6
  • 27
  • 38
  • 1
    A couple of points more: a) the proposed solution would hang if `notify` is called before `wait`. Since that methods are called on parallel threads, this well may happen. To avoid this, additional variable is needed, indicating the job is done. Usually such a variable contains the result. It should be checked before calling to `wait`. b) `wait` should be called in a loop, to ignore spurious notifications. – Alexei Kaigorodov Dec 14 '12 at 08:32
0

Here is one more implementation using join method

    class Example implements Runnable 
    {
        public void run()
        {
            doSomething();
        }
        public void doSomething(){
            System.out.println("Do something else");

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

    class Example2 implements Runnable 
    {
        Thread thread;
        Example example;

        public Example2(Example example){
            this.example = example;
        }


        public void run(){
            System.out.println("waiting for example 1 to complete");
            Thread t = new Thread(example);
            try{
                t.start();
                t.join();
            }catch(InterruptedException ie){

            }

            doSomething();    
        }

        public void doSomething(){
            System.out.println("Do something");
        }
    }

    public class Entry{
        public static void main(String[] args){

            Example example = new Example();

            Example2 obj = new Example2(example);
            Thread t = new Thread(obj);
            t.start();
        }
    }
Aniruddha
  • 3,513
  • 6
  • 27
  • 38
0

Not sure if your constrained to using this particular approach (wait/notify) however a better approach is taking advantage of the Java Concurrency API

public class ExampleCountDownLatch
{
    public void doSomething () throws InterruptedException
    {
        final CountDownLatch latch = new CountDownLatch(1);

        Thread thread = new Thread()
        {
            public void run ()
            {
                System.out.println("do something");
                latch.countDown();
            }
        };

        System.out.println("waiting for execution of method in your example class");
        thread.start();
        // wait for reasonable time otherwise kill off the process cause it took
        // too long.
        latch.await(3000, TimeUnit.MILLISECONDS);

        // now I can do something from your example 2
        System.out.println("now i can execute from example 2 do something else");
    }
}

Anyway just another approach if you had an option.

UPDATE:

Here is a blog about this very topic.

ramsinb
  • 1,985
  • 12
  • 17