Java多线程中join的用法

本文详细解析了Java中线程的join方法的作用及其应用场景,包括如何确保主线程等待子线程完成,以及如何利用join方法来控制多个线程之间的执行顺序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时计算,主线程会比子线程提前结束,如果主线程需要用到子线程返回的结果,就要用到join()方法了,这样就将异步的变为同步的了。


比如下面这个例子,如果不用join(),我们将无法控制运行流程


子线程随机休眠时间

public class ThreadA extends Thread{
	
	
	public void run() {
		try {
			int waitTime = (int) (Math.random()*1000);
			
			Thread.sleep(waitTime);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("子线程运行完了");
	}
}

public static void main(String[] args) throws InterruptedException {
		
	ThreadA thread = new ThreadA();
	thread.start();
	//Thread.sleep(2000);    这里我们并不知道应该设定多少时间才能当子线程运行完成后再运行主线程
	System.out.println("我想当子线程运行结束后再出现");
}


使用join()方法

public static void main(String[] args) throws InterruptedException {
		
	ThreadA thread = new ThreadA();
	thread.start();
	//Thread.sleep(2000);
	thread.join();  //加上子线程的join()方法后
	System.out.println("我想当子线程运行结束后再出现");
}

主线程会等待子线程运行完后再运行

join(long)方法中的参数表示,超过设定时间后就继续运行主线程,不再等待子线程了,这一点和sleep(long)很相似,但是两者是有区别的,join(long)内部是用wait(long)实现的,会释放锁,sleep(long)不释放锁;

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()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);    //这里是用了wait(long),会释放锁
                now = System.currentTimeMillis() - base;
            }
        }
    }

我们还可以通过join控制多个线程的执行顺序

思路:例如有三个线程a b c,我们可以在c线程中启动b线程,在b线程中启动a线程,这样,我们最先在主线程中启动c线程后,c会等待b线程执行完,b线程又会等待a线程执行完,这样产生的结果是a线程第一个执行完,b次之,c最后


public class ThreadC extends Thread {
	private ThreadB b;    //在c线程中启动b,需要持有b线程的对象
	
	public ThreadC(ThreadB b) {
		this.b = b;
	}

	public void run() {
		try {
			b.start();
			b.join();   //b线程与c线程合并,c会等待b执行完
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("线程C执行了");
	}
}

public class ThreadB extends Thread {
	private ThreadA a;   //在b线程中启动a,需要持有a线程的对象

	public ThreadB(ThreadA a) {
		this.a = a;
	}

	public void run() {
		try {
			a.start();
			a.join();    //a线程与b线程合并,b会等待a执行完
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("线程B执行了");
	}
}


public class ThreadA extends Thread{
	
	public void run() {
		System.out.println("线程A执行了");
	}
}

public static void main(String[] args)  {
	ThreadA a = new ThreadA();
	ThreadB b = new ThreadB(a);
	ThreadC c = new ThreadC(b);
		
	c.start();
}

运行结果

线程A执行了
线程B执行了
线程C执行了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值