开发者社区> 问答> 正文

Java多线程中关于join的问题? 探究 总结报错

"

代码一:

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线程阻塞在哪个线程上呢,为什么没有退出?

"

展开
收起
因为相信,所以看见。 2020-05-27 10:02:10 1302 0
1 条回答
写回答
取消 提交回答
  • 阿里,我所有的向往

    "

    探究

    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的方法定义,有以下几点逐一说明:

    • wait()方法在Object类定义,调用时会获取该对象上的监视器,因此必须在同步代码块上调用.从代码来看`public final synchronized void join(long millis)
      throws InterruptedException`,因此调用wait方法后,实际上是获取了当前对象(根据调试查看到是main线程)的监视器.
    • 根据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");
        }

    所以就会是这个结果

    "
    2020-05-27 17:36:15
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
Spring Cloud Alibaba - 重新定义 Java Cloud-Native 立即下载
The Reactive Cloud Native Arch 立即下载
多IO线程优化版 立即下载