多线程之join方法

大家好,又见面了,我是你们的朋友全栈君。

一.前言: 在很多情况下,我们都是通过主线程创建并启动子线程的,如果子线程中需要耗费大量的时间计算的话,主线程往往会比子线程先结束,这个时候就会导致有时候主线程想获取子线程计算之后的结果,但是却获取不到。这个时候,我们就可以通过join方法来解决这个问题。

二.join方法的作用:join方法的作用是使所属的线程对象x正常执行run()方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。方法join具有使线程排队运行的作用,有些类似同步的运行效果。

下面看一个例子:

代码语言:javascript复制public class MyThread extends Thread{

@Override

public void run() {

int sencondValue = (int)(Math.random()*1000);

System.out.println(sencondValue);

try {

Thread.sleep(sencondValue);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}代码语言:javascript复制public class Run {

public static void main(String[] args) throws InterruptedException {

MyThread myThread = new MyThread();

myThread.start();

myThread.join();

System.out.println("当对象myThread执行完毕后再执行");

}

}运行结果:

join的意思是使得放弃当前线程的执行,并返回对应的线程,例如上面代码的意思就是:程序在main线程中调用myThread线程的join方法,则main线程放弃cpu控制权,并返回myThread线程继续执行直到线程myThread执行完毕。所以结果是线程myThread执行完后,才到主线程执行,相当于在main线程中同步线程myThread,myThread执行完了,main线程才有执行的机会 此外,join方法和interrupt方法相遇的时候会抛出异常。

此外,还有join(long millis)方法,指定要等待多长时间。

三.join的实现原理:查看join方法源码:

代码语言:javascript复制/**

* Waits for this thread to die.

*

*

An invocation of this method behaves in exactly the same

* way as the invocation

*

*

* {@linkplain #join(long) join}{@code (0)}

*

*

* @throws InterruptedException

* if any thread has interrupted the current thread. The

* interrupted status of the current thread is

* cleared when this exception is thrown.

*/

public final void join() throws InterruptedException {

join(0);

}代码语言:javascript复制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;

}

}

}可以看出,join方法实际上是通过调用wait方法, 来实现同步的效果的。例如,A线程中调用了B线程的join方法,则相当于A线程调用了B线程的wait方法,在调用了B线程的wait方法后,A线程就会进入阻塞状态,因为它相当于放弃了CPU的使用权。需要注意的是,jdk规定,join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕,即join(0)等价于join()。

四.join方法和synchronized、sleep方法的区别:1.从上面的源码我们可以看出,join(long millis)是通过在内部使用wait(long millis)方法来实现的,所有它其实是具有释放锁的特点的,在执行完;而sleep(long millis)是不释放锁的,也就是如果有Synchronized同步块,其他线程仍然不能访问共享数据。注意该方法要捕获异常。

2.join在内部使用wait()方法进行等待,而synchronized关键字使用的是“对象监控器”原理做同步,具体可以看这个synchronized原理。

参考:https://www.2cto.com/kf/201608/543154.html

https://www.cnblogs.com/lcplcpjava/p/6896904.html

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/136897.html原文链接:https://javaforall.cn