java多线程join()详解

本文详细解析了Java中线程的join方法及其带参数的使用方式,对比了join(long)与sleep(long)的区别,并提供了具体的代码示例帮助理解。
摘要由CSDN通过智能技术生成

join()方法的作用:使所属的线程对象A正常执行,而使当前线程B进行无限期的阻塞,执行线程A执行结束销毁以后,线程B才会继续执行。

通过代码理解一下:

package join;

public class MyTest {
	public static void main(String[] args) throws InterruptedException {
		MyThread mt = new MyThread();
		mt.start();
		mt.join();
		System.out.println("main Thread end:" + System.currentTimeMillis());
	}
}
package join;

public class MyThread extends Thread {
	public void run() {
		System.out.println("MyThread begin:" + System.currentTimeMillis());
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

可以看出,main线程并没有立刻执行输出,而是等2秒以后,也就是MyThread线程执行结束以后,才继续执行。

join(long)方法:将上面的mt.join()改成mt.join(1000),执行结果

可以看出,mian线程只等待了1秒,并没有等待MyThread线程结束。

join(long)带参数的用法:

public class MyTest2 {
	public static void main(String[] args) throws InterruptedException {
		MyThreadA a = new MyThreadA();
		MyThreadB b = new MyThreadB(a);

		b.start();
		b.join(1000);
		System.out.println("打印1:" + System.currentTimeMillis());
		a.start();
		System.out.println("打印2:" + System.currentTimeMillis());
	}
}

public class MyThreadB extends Thread {
	private MyThreadA a;

	public MyThreadB() {
	}
	
	public MyThreadB(MyThreadA a) {
		this.a = a;
	}

	public void run() {
		synchronized (a) {
			try {
				System.out.println("MyThreadB 执行了:" + System.currentTimeMillis());
				Thread.sleep(5000);
				System.out.println("MyThreadB 执行结束了:" + System.currentTimeMillis());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class MyThreadA extends Thread {
	public synchronized void run() {
		try {
			System.out.println("MyThreadA 执行了:" + System.currentTimeMillis());
			Thread.sleep(5000);
			System.out.println("MyThreadA 执行结束:" + System.currentTimeMillis());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}


分析下执行过程:

1、main线程执行b.start()方法,b线程处于了就绪状态,此时cpu并没有把时间资源给b线程, 所以main线程接着执行了b.join(1000),main线程阻塞1秒钟。
2、b线程获得了时间资源执行了run()方法,并且获得了线程a的锁。
3、b线程执行sleep(5000),sleep()方法并不会释放锁,此时main线程等待了1秒以后,main线程处于了就绪状态,由于b线程还处于阻塞,因此main线程获得了时间资源,执行了‘打印1’。
4、main线程继续往下执行,调用a对象start(),由于start方法是同步的,因此main线程需要等b线程释放对象a的锁,所以main线程又进入阻塞状态。
5、5秒以后线程b释放对象a的锁,main线程获得了a的锁,执行了a.start()方法,此时a线程处于就绪状态,与第一条类似,main线程优先执行了‘打印2’。
6、最后线程a执行run()方法,5秒后结束

将MyThreadB类稍作修改。

public class MyThreadB extends Thread {
	private MyThreadA a;

	public MyThreadB() {
	}
	
	public MyThreadB(MyThreadA a) {
		this.a = a;
	}

	public void run() {
		try {
			Thread.sleep(2000);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		synchronized (a) {
			try {
				System.out.println("MyThreadB 执行了:" + System.currentTimeMillis());
				Thread.sleep(5000);
				System.out.println("MyThreadB 执行结束了:" + System.currentTimeMillis());
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

读者可以自行分析此执行结果的过程。

join(long)与sleep(long)的区别:两者最大的区别就在于,join(long)方法是使用wait(long)时间的,因此具有释放锁的效果,而sleep并不会释放锁。

最后附上start(),join()源码

public synchronized void start() {
        /**
	 * This method is not invoked for the main method thread or "system"
	 * group threads created/set up by the VM. Any new functionality added 
	 * to this method in the future may have to also be added to the VM.
	 *
	 * A zero status value corresponds to state "NEW".
         */
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        group.add(this);
        start0();
        if (stopBeforeStart) {
	    stop0(throwableFromStop);
	}
    }
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;
	    }
	}
    }
可以看出2个方法都是同步的。





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值