Java 中的join方法的常见用法

1.join方法的介绍:

join方法的作用是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。

join方法有线程排队的作用,join在内部使用wait()方法进行等待

2.join方法的使用一:

使用的背景一:有些情况下,主线程创建并启动了子线程,如果子线程中要进行大量的耗时运算,主线程往往将早于子线程之前结束,这时如果想等待子线程执行完成之后再结束,如果子线程处理了一个数据,主线程要获取这个数据中的值,就要用到join方法。

代码实现:

class MyThread extends Thread {

	@Override
	public void run() {
		try {
			int secondValue = (int) (Math.random() * 10000);
			System.out.println(secondValue);
			Thread.sleep(secondValue);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

public class HighConcurrency {

	public static void main(String[] args) {
		try {
			MyThread threadTest = new MyThread();
			threadTest.start();
			threadTest.join();		//执行到这句的时候,当前线程执行wait()方法,直到threadTest执行完,再唤醒当前线程

			System.out.println("我想当threadTest对象执行完毕后我再执行,我做到了");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
输出结果:
762
我想当threadTest对象执行完毕后我再执行,我做到了

分析:当执行到threadTest.join()这步时,join方法内部是调用的wait()方法,让当先线程进入等待,直到threadTest线程执行完后,会自动唤醒当前线程,继续执行。

3.join方法的使用二:

join使用的背景二:有三个线程T1,T2,T3如何保证它们顺序执行

代码实现:

public class HighConcurrency {
	 
    // 1.现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行
 
    public static void main(String[] args) {
 
        final Thread t1 = new Thread(new Runnable() {
 
            @Override
            public void run() {
                System.out.println("t1");
            }
        });
        final Thread t2 = new Thread(new Runnable() {
 
            @Override
            public void run() {
                try {
                    // 引用t1线程,等待t1线程执行完
                    t1.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t2");
            }
        });
        Thread t3 = new Thread(new Runnable() {
 
            @Override
            public void run() {
                try {
                    // 引用t2线程,等待t2线程执行完
                    t2.join();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("t3");
            }
        });
        t3.start();//这里三个线程的启动顺序可以任意,大家可以试下!
        t2.start();
        t1.start();
    }
}

程序输出:

t1
t2
t3

任意改变t3.start(),t2.start(),t1.start()的顺序,结果都是输出t1,t2,t3。查看下面join的源码,但是这里注意线程如果被生成,但是还未被启动,调用它的join()方法是没有作用的,将直接向下执行。我自己的理解是:在t3.start()执行后,在run方法中执行t2.join()前t2.start()已经执行,所以join源码中的while(isAlive)中的wait(0)才会执行。为了验证自己的想法,将

 t3.start();//这里三个线程的启动顺序可以任意,大家可以试下!
 t2.start();
 t1.start();

改为

   t3.start();//这里三个线程的启动顺序可以任意,大家可以试下!
        try {
			Thread.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
        t2.start();
        t1.start();
此时的输出:
t3
t1
t2
所以这段代码是不可靠的,如果t3.start()执行后t2没有即使开启,就会达不到我们想要的效果。

join方法的源码:

/** 
     *  Waits at most <code>millis</code> milliseconds for this thread to   
     * die. A timeout of <code>0</code> means to wait forever.   
     */  
    //此处A timeout of 0 means to wait forever 字面意思是永远等待,其实是等到t结束后。  
    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;  
            }  
        }  
    }  

这里出现了wait(0),那么wait(0)是什么意思呢,查看wait()方法,wait(0)就是让其一直等待。

public final void wait() throws InterruptedException {
    wait(0);
}

而wait(long timeout),该方法与wait()方法类似,唯一的区别是在指定时间内,如果没有notify或notifyAll方法唤醒,也会自动唤醒。


参考:

Java多线程中join方法的理解:https://www.nowcoder.com/questionTerminal/d8a288fc416c4d638dfb042e1be239fc?from=14pdf

Java并发编程,线程间的协作:http://www.cnblogs.com/paddix/p/5381958.html

猜你喜欢

转载自blog.csdn.net/chenkaibsw/article/details/80912878