一、一个例子
private static void joinTest(List<String> roles) {
Vector<Thread> vector = new Vector<>(10);
for (int i=0;i<10;i++){
MyThread myThread = new MyThread("id"+i,"name"+i,roles);
Thread t = new Thread(myThread);
vector.add(t);
t.start();
}
for (Thread thread : vector){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class MyThread implements Runnable{
private String id;
private String name;
private List<String> roles;
public MyThread(String id,String name,List<String> roles){
this.name = name;
this.id = id;
this.roles = roles;
}
@Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
roles.add(name);
System.out.println("执行了-id:"+id+"name:"+name+"roles size:"+roles.size());
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<String> getRoles() {
return roles;
}
public void setRoles(List<String> roles) {
this.roles = roles;
}
}
输出结果:
开始:1515250426924
执行了-id:id2name:name2roles size:1
执行了-id:id1name:name1roles size:3
执行了-id:id0name:name0roles size:2
执行了-id:id4name:name4roles size:4
执行了-id:id6name:name6roles size:7
执行了-id:id7name:name7roles size:8
执行了-id:id8name:name8roles size:9
执行了-id:id5name:name5roles size:6
执行了-id:id3name:name3roles size:5
执行了-id:id9name:name9roles size:10
[name2, name0, name1, name4, name3, name5, name6, name7, name8, name9]
结束:1515250427932耗时:1008roles size:10
可以看出,上面每个线程执行1000ms,总时长1008ms.
二、源码分析
/**
- Waits for this thread to die.
- <p> An invocation of this method behaves in exactly the same
- way as the invocation
- <blockquote>
- {@linkplain #join(long) join}{@code (0)}
- </blockquote>
- @throws InterruptedException
if any thread has interrupted the current thread. The
<i>interrupted status</i> of the current thread is
cleared when this exception is thrown.
*/
public final void join() throws InterruptedException {
join(0);
}
这里看清楚一点:join传参为0。
然后进入join方法:
/**
- Waits at most {@code millis} milliseconds for this thread to
- die. A timeout of {@code 0} means to wait forever.
- <p> This implementation uses a loop of {@code this.wait} calls
- conditioned on {@code this.isAlive}. As a thread terminates the
- {@code this.notifyAll} method is invoked. It is recommended that
- applications not use {@code wait}, {@code notify}, or
- {@code notifyAll} on {@code Thread} instances.
- @param millis
the time to wait in milliseconds
- @throws IllegalArgumentException
if the value of {@code millis} is negative
- @throws InterruptedException
if any thread has interrupted the current thread. The
<i>interrupted status</i> of the current thread is
cleared when this exception is thrown.
*/
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;
}
}
}
从源码可以看出,如果线程被生成了,但还未被起动,isAlive()将返回false,调用它的join()方法是没有作用的,将直接继续向下执行wait。而wait方法中有参数,也就是不用唤醒谁,只是不再执行wait,向下继续执行而已。
三、join总结
join方法的原理就是调用相应线程的wait方法进行等待操作的,例如A线程中调用了B线程的join方法,则相当于在A线程中调用了B线程的wait方法,当B线程执行完(或者到达等待时间),B线程会自动调用自身的notifyAll方法唤醒A线程,从而达到同步的目的。
网友评论