在本教程中,我们将讨论Thread类中的不同*join()*方法 。我们将详细介绍这些方法和一些示例代码。
与 wait()和notify()方法一样,*join()*是另一种线程间同步机制。
您可以快速查看本教程, 以了解有关wait()和notify()的更多信息。
join方法在Thread 类中定义:
public final void join()throws InterruptedException
等待此线程死亡。
**当我们在线程上调用*join()*方法时,调用线程进入等待状态。它一直处于等待状态,直到引用的线程终止。
我们可以在以下代码中看到此行为:
class SampleThread extends Thread {
public int processingCount = 0;
SampleThread(int processingCount) {
this.processingCount = processingCount;
LOGGER.info("Thread Created");
}
@Override
public void run() {
LOGGER.info("Thread " + this.getName() + " started");
while (processingCount > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
LOGGER.info("Thread " + this.getName() + " interrupted");
}
processingCount--;
}
LOGGER.info("Thread " + this.getName() + " exiting");
}
}
@Test
public void givenStartedThread() throws InterruptedException {
Thread t2 = new SampleThread(1);
t2.start();
LOGGER.info("Invoking join");
t2.join();
LOGGER.info("Returned from join");
assertFalse(t2.isAlive());
}
在执行代码时,我们应该期望类似于以下结果:
INFO: Thread Created
INFO: Invoking join
INFO: Thread Thread-1 started
INFO: Thread Thread-1 exiting
INFO: Returned from join
如果引用的线程被中断,join()方法也可能返回。在这种情况下,该方法抛出 InterruptedException。
最后,*如果引用的线程已经终止或尚未启动,调用*join()方法则立即返回。
Thread t1 = new SampleThread(0);
t1.join(); //returns immediately
在*join()方法将保持如果引用的线程被阻塞或时间过长处理等。这可能成为一个问题,因为调用线程将变得无响应。为了处理这些情况,我们使用了join()*方法的重载版本 ,允许我们指定超时期限。
*有两个定时版本重载*join()方法:
public final void join(long millis) throws InterruptedException
最多等待millis的毫秒该线程终止,超时为0意味着永远等待。public final void join(long millis,int nanos) throws InterruptedException
最多等待 millis 毫秒加上 nanos 纳秒该线程死亡。
我们可以使用如下的超时join():
@Test
public void givenStartedThread_waitsUntilTimedout() throws InterruptedException {
Thread t3 = new SampleThread(10);
t3.start();
t3.join(1000);
assertTrue(t3.isAlive());
}
在这种情况下,调用线程等待大约1秒钟,以便线程t3完成。如果线程t3在此时间段内没有完成,则*join()*方法将控制权返回给调用方法。
定时*join()*取决于操作系统的计时。因此,我们不能确定 *join()*将完全等待指定的时间。
除了等到终止之外,调用 *join()*方法还具有同步效果。join()创建一个before-before关系:
“从该线程上的join()成功返回之前,线程中的所有操作都可能发生在任何其他线程。”
这意味着当线程t1调用t2.join()时,t2完成的所有更改在返回时在t1中可见。但是,如果我们不调用 join() 或使用其他同步机制,我们无法保证其他线程中的更改对当前线程可见,即使其他线程已完成。
因此,即使*join()*方法调用处于终止状态的线程立即返回,我们仍然需要在某些情况下调用它。
我们可以在下面看到一个不正确同步代码的示例:
SampleThread t4 = new SampleThread(10);
t4.start();
// not guaranteed to stop even if t4 finishes.
do {
} while (t4.processingCount > 0);
为了正确同步上面的代码,我们可以 在循环中添加定时的 *t4.join()*或使用其他一些同步机制。
*join()*方法对于线程间同步非常有用。在本文中,我们讨论了 *join()方法及其行为。我们还使用join()*方法检查了代码。
关注公众号:「Java知己」,每天更新Java知识哦,期待你的到来!