8

I wan't to be sure that some piece of my code within the main thread will be executed after some piece of code executed withing the secondary thread. Here's what I got:

    final Object lock = new Object();
    final Thread t = new Thread(new Runnable() {
        public void run() {
            synchronized(lock) {
                System.out.println("qwerty");
                lock.notify();
            }
        }
    });

    synchronized(lock) {
        t.start();
        lock.wait();
    }

    System.out.println("absolutely sure, qwerty is above");
  1. Is it correct solution?
  2. Any shorter ways to do the same?
Andrey Agibalov
  • 7,624
  • 8
  • 66
  • 111

4 Answers4

13

Things like notify() and wait() are really low-level synchronization primitives.

You should use higher-level abstractions whenever possible, like in this case, say, a CountDownLatch.

The following is just an example that should get you started (for example the timeout issues aren't taken into account here):

    final CountDownLatch latch = new CountDownLatch(1);
    final Thread t = new Thread(new Runnable() {
        public void run() {
            System.out.println("qwerty");
            latch.countDown();
        }
    });

    t.start();
    latch.await();

    System.out.println("absolutely sure, qwerty as been printed");

Low-level things like wait and notify are really just low-level Java idiosynchrasies that you shouldn't be concerned with (unless you're writing concurrency APIs).

Additionally, I'd suggest reading the amazing book: Java Concurrency In Practice.

SyntaxT3rr0r
  • 27,745
  • 21
  • 87
  • 120
5

Assuming that your main thread needs to initiate the secondary thread's processing, an Exchanger would be the simplest solution.

If the secondary thread is independent, then some form of BlockingQueue would be appropriate.


An example using Exchanger (with proper exception handling). The one Exchanger could be substituted with two queues.

public static void main(String[] argv)
throws Exception
{
    final Exchanger<String> exchanger = new Exchanger<String>();
    new Thread(new Runnable() 
    {
        @Override
        public void run() 
        {
            try
            {
                String s = exchanger.exchange("");
                System.out.println(s);
                exchanger.exchange("this came from subthread");
            }
            catch (InterruptedException ex)
            {
                System.out.println("interrupted while waiting for message");
            }
        }
    }).start();

    exchanger.exchange("this came from main thread");
    String s = exchanger.exchange("");
    System.out.println(s);
}
parsifal
  • 1,507
  • 8
  • 7
-1
final Thread t = new Thread(new Runnable() {
    public void run() {
        System.out.println("qwerty");
    }
});

t.start();
t.join();

System.out.println("absolutely sure, qwerty is above");
DoubleMalt
  • 1,263
  • 12
  • 17
  • Just saw that while it solves the primitive example above, it doesn't do what the question specified if the subthread should do something else ... – DoubleMalt Aug 12 '11 at 15:56
-4

The best solution for the code you have given is:

System.out.println("qwerty");
System.out.println("absolutely sure, qwerty is above");

Don't use threading when you don't need it.

But if you know what you're doing with the thread, then @DoubleMalt's solution is the way to go (t.join()).

You'd also probably find it worth reading http://download.oracle.com/javase/tutorial/essential/concurrency/

avh4
  • 2,635
  • 1
  • 22
  • 25