Easier way to synchronize 2 threads in Java?

2019-06-20 23:05发布

问题:

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?

回答1:

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


回答2:

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.



回答3:

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


回答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/