java多线程join()详解

来源:互联网 发布:西安seo服务 编辑:程序博客网 时间:2024/06/07 11:56

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个方法都是同步的。





0 0
原创粉丝点击