join()方法
- join() 等待这个线程死亡
说人话:在很多情况下,主线程创建并启动子线程,如果子线程中要进行大量的耗时运算,主线程将早于子线程结束。这时,如果主线程想等子线程执行完成才结束,比如子线程处理一个数据,主线程想要获得这个数据中的值,就要用到join()方法了。方法join()的作用是等待线程对象销毁。 - join(long millis) 此线程最多等待 millis毫秒。
说人话:join方法中如果传入参数,则表示这样的意思:如果A线程中掉用B线程的join(10),则表示A线程会等待B线程执行10毫秒,10毫秒过后,A、B线程并行执行。需要注意的是,jdk规定,join(0)的意思不是A线程等待B线程0秒,而是A线程等待B线程无限时间,直到B线程执行完毕,即join(0)等价于join()。(其实join()中调用的是join(0)) - join(long millis, int nanos) 此线程最多等待 millis毫秒加上 nanos纳秒。
另外:join方法必须在线程start方法调用之后调用才有意义。这个也很容易理解:如果一个线程都没有start,那它也就无法同步了。
对于join原码:
(使用wait(long)来实现的,所以join(long)方法具有释放锁的特点)
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;
}
}
}
通过下面代码:
package com.gem.demo.day0810;
public class Thread01 {
public static void main(String[] args) {
MyThread01 t1 = new MyThread01();
long start = System.currentTimeMillis();
t1.start();
try {
t1.join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis() - start);
System.out.println("Main finished");
}
}
class MyThread01 extends Thread {
@Override
public void run() {
//synchronized (currentThread()) {
for (int i = 1; i <= 5; i++) {
try {
sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ">" + i);
}
System.out.println(Thread.currentThread().getName() + " finished");
//}
}
}
运行结果:
main线程等待(放弃cpu使用权)了t线程1000毫秒之后,结束了,随后是t1线程打印的数据。
去掉synchronized注释后,运行结果:
由于先调用了t.start()方法,线程进入synchronized代码段,main线程等待一秒以后,还是得不到线程t的对象锁,只能继续等待,直到线程t结束,释放锁。
细说join()、wait()方法区别,