"
代码一:
public static void main(String[] args) throws Exception { Thread thread = new Thread(() -> { try { TimeUnit.SECONDS.sleep(10); System.out.println("thread-0 thread exit."); } catch (InterruptedException e) { e.printStackTrace(); } }, "thread-0"); thread.start(); thread.join(); System.out.println("main thread exit."); }
 
控制台(10s后打印并退出):
thread-0 thread exit.
main thread exit.
Process finished with exit code 0 
代码二:
public static void main(String[] args) throws Exception {
    Thread.currentThread().join();
    System.out.println("main thread exit.");
  } 
控制台(一直等待中):
问题:第一段代码是main线程阻塞在thread-0线程上,当thread-0执行完毕,main线程也同时退出,那第二段代码中main线程阻塞在哪个线程上呢,为什么没有退出?
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
"
public static void main(String[] args) throws Exception { Thread.currentThread().join(); System.out.println("main thread exit."); }
 
为了了解问题本质,我们跟进去代码看看,线程的join方法如下:
public final void join() throws InterruptedException {
        join(0);
    } 
再继续跟:
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()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    } 
根据代码,其实join方法最终是待用了wait(0);这行代码,而wait方法是本地方法.
根据wait的方法定义,有以下几点逐一说明:
<ul>
  
<li>Some other thread invokes the {@code notify} method for this
      object and thread <var>T</var> happens to be arbitrarily chosen as
      the thread to be awakened.
     
<li>Some other thread invokes the {@code notifyAll} method for this
      object.
      
<li>Some other thread {@linkplain Thread#interrupt() interrupts}
      thread <var>T</var>.
      
<li>The specified amount of real time has elapsed, more or less.  If
      {@code timeout} is zero, however, then real time is not taken into
      consideration and the thread simply waits until notified.
</ul> 
因此,回答你的问题就是,join方法实质是调用了wait方法.wait方法调用后阻塞(我不认为这是阻塞)在当前线程(main线程上),根据wait的定义,不调用notify,notifyAll,interrupt以及超时机制(本例调用的是wait(0),故不存在这种情况),那么线程将一直处于等待状态,故一直不会退出。
######main线程阻塞自己
######大致的说下吧,Thread中,join()方法的作用是调用线程等待该线程完成后,才能继续用下运行。
public static void main(String[] args) throws InterruptedException
    {
        System.out.println("main start");
        Thread t1 = new Thread(new Worker("thread-1"));
        t1.start();
        t1.join();
        System.out.println("main end");
    } 
在上面的例子中,main线程要等到t1线程运行结束后,才会输出“main end”。如果不加t1.join(),main线程和t1线程是并行的。而加上t1.join(),程序就变成是顺序执行了。
我们在用到join()的时候,通常都是main线程等到其他多个线程执行完毕后再继续执行。其他多个线程之间并不需要互相等待。
下面这段代码并没有实现让其他线程并发执行,线程是顺序执行的。
public static void main(String[] args) throws InterruptedException
    {
        System.out.println("main start");
        Thread t1 = new Thread(new Worker("thread-1"));
        Thread t2 = new Thread(new Worker("thread-2"));
        t1.start();
        //等待t1结束,这时候t2线程并未启动
        t1.join();
        
        //t1结束后,启动t2线程
        t2.start();
        //等待t2结束
        t2.join();
        System.out.println("main end");
    } 
所以就会是这个结果
"