join方法的作用是让调用这个方法的线程对象执行完成后才会执行别的线程的代码。
利用join等待线程完成。这里就要引出一个概念:线程同步
/**
* 利用join等待线程完成后执行
*/
public class JoinDemo1 {
static int num=0;
public static void main(String[] args) {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
num=10;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A");
t1.start();
try {
//t1线程执行玩后,下面的输出语句才会执行,没有这行,输出语句很可能输出0
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(num);
}
}
例二:两个线程的同步
前面例子只有一个线程,现在变成两个,并且计算总耗时。代码如下。
问题是最后的总耗时是多少?
/**
* 两个线程join并计算时间
*/
public class JoinDemo2 {
static int num=0;
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num=10;
}
},"A");
Thread t2=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
num=10;
}
},"B");
t1.start();
t2.start();
long start=System.currentTimeMillis();
System.out.println("t1 join start");
t1.join();
System.out.println("t1 join end");
System.out.println("t2 join start");
t2.join();
System.out.println("t2 join end");
long end=System.currentTimeMillis();
System.out.println("cost:"+(end-start));
}
}
总耗时是5s。
运行逻辑是两个线程差不多同时开始运行,t1调用join后,t2还是会继续运行的,只是main方法后面的代码不运行了。差不多3s后,t1执行完成,调用t2的join方法,main方法后面的代码又卡住,差不多2s后,t2完成,main方法里面的代码继续执行,输出结果。
t1 join start
//停了3s
t1 join end
t2 join start
//停了2s
t2 join end
cast:5001
如果t1和t2 join换个位置会怎么样?
耗费的时间还是5s,t2的join时间几乎为0,因为t2执行完成的时候,t1已经完成了。象征性的join一下。
System.out.println("t2 join start");
t2.join();
System.out.println("t2 join end");
System.out.println("t1 join start");
t1.join();
System.out.println("t1 join end");
t2 join start
//停了5s
t2 join end
t1 join start
t1 join end
cost:5002
有时限的join
join方法还有一个时限参数,可以设置最长等待的时间,如果超过时间就不等待了。
public class JoinDemo3 {
static int num=0;
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
num=10;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A");
t1.start();
long start=System.currentTimeMillis();
t1.join(2000);
long end=System.currentTimeMillis();
System.out.println("cost:"+(end-start));
System.out.println(num);
}
}
t1执行完成需要3s但只等待2s,2s后main线程的代码就继续执行了。所以num的值还是0.
cost:2000
0
如果join的时间大于线程实际运行的时间,那么和不加是一样的效果。
public class JoinDemo3 {
static int num=0;
public static void main(String[] args) throws InterruptedException {
Thread t1=new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(3000);
num=10;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"A");
t1.start();
long start=System.currentTimeMillis();
t1.join(4000);
long end=System.currentTimeMillis();
System.out.println("cost:"+(end-start));
System.out.println(num);
}
}
cost:3000
10