join()方法:
在主线程创建并启动子线程,如果子线程需要太长时间,主线程会提前结束,等子线程完成run方法后,子线程结束。
但是有时候我们需要等待子线程完成后再执行主线程。例如:子线程处理一个数据,主线程需要取得这个数据,就需要使用join方法了。
package join;
public class MyThread extends Thread{
public void run() {
try {
int secondValue=(int) (Math.random()*10000);
System.out.println(secondValue);
Thread.sleep(secondValue);
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
package join;
public class Test {
public static void main(String[] args) {
try {
MyThread mythread=new MyThread();
mythread.start();
mythread.join();
System.out.println("mythread执行完输出☆☆☆☆☆");
}catch(InterruptedException e) {
e.printStackTrace();
}
}
}
控制台输出:
9808
mythread执行完输出☆☆☆☆☆
以上就是join的使用。
从join方法的特性我们了解到,join具有使得线程排队的效果,就像同步一样。但是join方法底层使用的是wait方法。
下面我们来看看join的源码:
public final void join() throws InterruptedException {
join(0);
}
对,没错这个就是join的源码。当然它调用了join(long millis)方法,所以下面来看一下join(long millis)方法:
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(long millis)方法的参数是0时,运行这个方法的线程就会执行wait(0)。我们再看看wait的源码:
public final void wait() throws InterruptedException {
wait(0);
}
其实wait()方法其实执行的就是wait(0)。所以主线程一直等待。那么主线程是怎么被唤醒的呢?
我们看join(long milis)源码可以知道,这个方法使用synchronized修饰符的,也就是调用这个方法需要获得子线程对象的锁,然后调用wait,即先获得锁后释放锁,然后等待唤醒。
After run() finishes, notify() is called by the Thread subsystem.
当线程运行结束的时候,notify是被线程的子系统调用的
分别以普通对象和线程对象作为锁,当使用线程对象作为所得时候,如果锁对象执行完毕了。wait就会停止等待继续执行
public class ThreadTestl {
public static void main(String[] args) {
final MyLockThread mylockthread = new MyLockThread();
//final Object mylockthread = new Object();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (mylockthread) {
System.err.println(1);
try {
mylockthread.wait(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.err.println(2);
}
}
}).start();
mylockthread.start();
}
static class MyLockThread extends Thread {
public MyLockThread() {
}
@Override
public void run() {
System.err.println("MyLockThread");
}
}
}
所以到现在我们知道了join的工作原理了。