join()方法
public class TestJoin implements Runnable {
public static void main(String[] sure) throws InterruptedException {
Thread t = new Thread(new TestJoin());
long start = System.currentTimeMillis();
t.start();
t.join(1000);//等待线程t 1000毫秒
System.out.println(System.currentTimeMillis()-start);//打印出时间间隔
System.out.println("Main finished");//打印主线程结束
}
@Override
public void run() {
//理解这里为何不用this关键字,this指代new TestJoin(),而currentThread()指代new Thread(new TestJoin())
synchronized (Thread.currentThread()) {//这个同步锁是和上面的t.join()方法互斥*****
for (int i = 1; i <= 5; i++) {
try {
TimeUnit.SECONDS.sleep(1);//睡眠5秒,循环是为了方便输出信息
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("睡眠" + i);
}
System.out.println("TestJoin finished");//t线程结束
}
}
}
解析:
1. Thread对象t也只是个对象, 他不代表线程执行流, t这个对象即可以被主线程使用, 也可以被新启动的线程使用
2. run()方法里this和Thread.currentThread()的区别注意 https://blog.csdn.net/smartboy_01/article/details/89356010
Thread.currentThread()是获得当前线Thread对象的引用
3. 如果主线程的join()方法先获得t对象的锁, 则主线程先等待子线程1s,同时释放对象t的锁, 子线程开始执行获得对象t的锁并休眠5s后释放对象t的锁, 主线程获得对象t的锁并结束等待继续向下执行, 总时间5s(主线程等待的1s包含在内)
如果子线程的方法先获得对象t的锁,并休眠5s后释放锁,并结束子线程. 主线程获得对象t的锁,但是因为子线程已经结束运行,join方法不再等待直接向下运行, 所以总时间还是5s
jdk中join方法的源码
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {//这个分支是无限期等待直到b线程结束
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
join方法是依靠wait方法来实现的, 并且join方法是一个同步方法
从代码上看,如果线程被生成了,但还未被起动,调用它的 join() 方法是没有作用的,将直接继续向下执行
Join方法实现是通过wait(小提示:Object 提供的方法)。 当main线程调用t.join时候,main线程会获得线程对象t的锁(wait 意味着拿到该对象的锁),调用该对象的wait(等待时间),直到该对象唤醒main线程 ,比如退出后。这就意味着main 线程调用t.join时,必须能够拿到线程t对象的锁
所以上述代码的执行结果分两种情况,如果主方法中的 t.join(1000) 方法先获取锁, 执行wait方法, 然后当前线程阻塞, 释放对象锁, 接着线程t启动获取对象锁, 休眠5秒并继续持有对象锁, 然后释放锁, wait方法虽然阻塞1s就结束, 但是因为未能继续获取锁, 只能等待t线程休眠5s释放锁后再持有锁, 即main方法退出持续了5s
如果是t线程先获取锁, 则main方法退出则持续了5+1s ??? 实际上怎么都是5s why?????????? 是否因为t线程结束后,t.join方法失效
注意, wait方法的执行, 需要先获取锁, 在进入阻塞状态后会释放锁, wait在唤醒后继续向下执行的前提是需要再次获取锁

浙公网安备 33010602011771号