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在唤醒后继续向下执行的前提是需要再次获取锁

posted @ 2017-08-15 17:02  車輪の唄  阅读(16)  评论(0)    收藏  举报  来源