如何等待线程等待

时间:2016-09-05 11:01:45

标签: java multithreading join wait

我想等到线程进入等待状态。我一直在尝试使用join(见下文),但它没有用。怎么做到这一点?

public Test() {
    System.out.print("Started");
    Thread thread = new Thread(() -> {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        synchronized (Test.class) {
            try {
                Test.class.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    thread.start();

    try {
        thread.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.print("Done");
}

完成从未打印过。

1 个答案:

答案 0 :(得分:1)

你的主线程没有超越join(),因为第二个线程永远不会结束。第二个帖子永远不会结束,因为它正在Test.class等待通知,但没有人通知它。

如果希望主线程在第二个线程到达Test.class.wait();行时继续执行,则需要为此同步引入另一个监视器。主线程必须在此监视器上等待,并且第二个线程必须在准备切换到等待状态时通知它:

System.out.println("Started");
final Object monitor = new Object();
Thread thread = new Thread(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("Finished");
    synchronized (monitor) {
        monitor.notify();  // Notify the main thread
    }
    synchronized (Test.class) {
        try {
            Test.class.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
});
thread.start();

synchronized (monitor) {
    try {
        monitor.wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
System.out.println("Done");

这段代码可行,但看起来有点难看。它还会留下一个挂起的线程,阻止程序正常终止。如果您希望此线程完成,则需要有人致电Test.class.notify()

从您的问题中不清楚您一般会尝试实现的目标。如果你想要产生一个线程并等到它完成,你就不需要那些wait()notify(),只需使用join()

System.out.println("Started");
Thread thread = new Thread(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println("Finished");
});
thread.start();

try {
    thread.join();
} catch (InterruptedException e) {
    e.printStackTrace();
}
System.out.println("Done");

还有一件事:在构造函数中创建和启动线程是一个非常糟糕的主意。为此使用单独的方法(如initialize())。