zoukankan      html  css  js  c++  java
  • Java Thread.join()方法

    一、使用方式。

    join是Thread类的一个方法,启动线程后直接调用,例如:

    Thread t = new AThread(); t.start(); t.join();

    二、为什么要用join()方法

    在很多情况下,主线程生成并起动了子线程,如果子线程里要进行大量的耗时的运算,主线程往往将于子线程之前结束,但是如果主线程处理完其他的事务后,需要用到子线程的处理结果,也就是主线程需要等待子线程执行完成之后再结束,这个时候就要用到join()方法了。

    三、join方法的作用

    在JDk的API里对于join()方法是:

    join

    public final void join() throws InterruptedException Waits for this thread to die. Throws: InterruptedException  - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.

    即join()的作用是:“等待该线程终止”,这里需要理解的就是该线程是指的主线程等待子线程的终止。也就是在子线程调用了join()方法后面的代码,只有等到子线程结束了才能执行

    四、用实例来理解

    package com.tonyluis;
    class BThread extends Thread {
        public BThread() {
            super("Thread B");//threadName
        };
        public void run() {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + " start");
            try {
                for (int i = 0; i <= 5; i++) {
                    System.out.println(threadName + " loop at " + i);
                	Thread.sleep(1000);//1000ms执行一次,便于计时
                }
                System.out.println(threadName + " end");
            } catch (Exception e) {
                System.out.println("Exception from " + threadName);
            }
        }
    }
    class AThread extends Thread {
        BThread bt;
        public AThread(BThread bt) {
            super("Thread A");
            this.bt = bt;
        }
        public void run() {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + " start");
            try {
                bt.join();//先执行bt线程
                System.out.println(threadName + " end");
            } catch (Exception e) {
                System.out.println("Exception from " + threadName);
            }
        }
    }
    public class TestThreadJoin {
        public static void main(String[] args) {
            String threadName = Thread.currentThread().getName();
            System.out.println(threadName + " start");//main Thread
            BThread bt = new BThread();
            AThread at = new AThread(bt);
            try {
                bt.start();
                Thread.sleep(2000);//主线程休息,正好执行两个Loop
                at.start();
                at.join();//让主线程等待at线程,否则主线程直接往下执行了
            } catch (Exception e) {
                System.out.println("Exception from main");
            }
            System.out.println(threadName + " end!");
        }
    }
    

    运行结果:

    main start
    Thread B start
    Thread B loop at 0
    Thread B loop at 1
    Thread B loop at 2//可能执行两个Loop也可能3个Loop
    Thread A start
    Thread B loop at 3
    Thread B loop at 4
    Thread B loop at 5
    Thread B end
    Thread A end
    main end!

    五、从源码看join()方法

    在AThread的run方法里,执行了bt.join();,进入看一下它的JDK源码:

    public final void join() throws InterruptedException {
        join(0L);//后面参数为wait的最大时间,如果是0表示永远等待直到该线程执行完毕
    }

    然后进入join(0L)方法:

    public final synchronized void join(long l)
        throws InterruptedException
    {
        long l1 = System.currentTimeMillis();
        long l2 = 0L;
        if(l < 0L)
            throw new IllegalArgumentException("timeout value is negative");
        if(l == 0L)
            for(; isAlive(); wait(0L));
        else
            do
            {
                if(!isAlive())
                    break;
                long l3 = l - l2;
                if(l3 <= 0L)
                    break;
                wait(l3);
                l2 = System.currentTimeMillis() - l1;
            } while(true);
    }

    单纯从代码上看:

    如果线程被生成了,但还未被起动,isAlive()将返回false,调用它的join()方法是没有作用的。将直接继续向下执行。

    在AThread类中的run方法中,bt.join()是判断bt的active状态,如果bt的isActive()方法返回false,在 bt.join(),这一点就不用阻塞了,可以继续向下进行了。从源码里看,wait方法中有参数,也就是不用唤醒谁,只是不再执行wait,向下继续执 行而已。

    在join()方法中,对于isAlive()和wait()方法的作用对象是个比较让人困惑的问题:

    isAlive()方法的签名是:public final native boolean isAlive(),也就是说isAlive()是判断当前线程的状态,也就是bt的状态。

    wait()方法在jdk文档中的解释如下:

    Causes the current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object. In other words, this method behaves exactly as if it simply performs the call wait(0).

    The current thread must own this object's monitor. The thread releases ownership of this monitor and waits until another thread notifies threads waiting on this object's monitor to wake up either through a call to the notify method or the notifyAll method. The thread then waits until it can re-obtain ownership of the monitor and resumes execution.

    在这里,当前线程指的是at。

  • 相关阅读:
    vue分页效果
    百度联想
    【java基础之jdk源码】集合类
    【java基础之jdk源码】Object
    深入理解abstract class和interface
    mysql索引类型 normal, unique, full text
    JSP中两种include的区别
    详解mysql int类型的长度值问题
    《Think in JAVA》之每日一读(initianlize)——2013/11/12、13
    探索ORM ————iBati(一)
  • 原文地址:https://www.cnblogs.com/tonyluis/p/5475747.html
Copyright © 2011-2022 走看看