假如有这样一个场景,程序员小余今天的任务是:实现3个需求,修改3个bug,完成这些之后才能下班。可以使用两种方法实现。
1.使用join方法
代码如下:
public class JoinTest {
public static void main(String[] args) throws InterruptedException{
Thread thread1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i =1;i<4;i++) {
System.out.println( "已实现了第"+i+"需求");
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1;i<4;i++) {
System.out.println("已修改完第"+i+"个Bug");
}
}
});
thread1.start();
thread2.start();
thread1.join();
thread2.join();
System.out.println( "任务完成,可以下班了");
}
}
执行了很多次,结果都符合要求,随机选择一次结果如下:
可以看到,程序员小余是实现完需求并且改完bug才下班的。如果不调用线程1和线程2的join方法话,就不能保证是完成任务后才下班的。查看join方法的实现代码可以看到如下代码:
while (isAlive()) {
wait(0);
}
其原理就是不停检查join线程是否存活,如果join线程存活则让当前线程永远等待。直到线程中止后,线程的this.notifyAll()方法才会调用,调用notifyAll()方法是在JVM里实现的,所以JDK里看不到。
2.使用CountDownLatch
在JDK1.5之后的并发包中提供了CountDownLatch也可以实现join的功能,它允许一个或多个线程等待其他线程完成操作。
常用API如下:
CountDownLatch(int count) //实例化一个倒计数器,count指定计数个数
countDown() // 计数减一
await() //等待,当计数减到0时,所有线程并行执行
下面使用CountDownLatch来实现之前的代码:
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest {
static final CountDownLatch c = new CountDownLatch(6);//构造一个大小的为6的计数器
public static void main(String[] args) throws InterruptedException {
Thread thread1 = new Thread(new Runnable(){
@Override
public void run() {
for(int i =1;i<4;i++) {
System.out.println( "已实现了第"+i+"需求");
c.countDown();//执行一次该线程,计数器减1
}
}
});
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
for(int i = 1;i<4;i++) {
System.out.println("已修改完第"+i+"个Bug");
c.countDown();//执行一次该线程,计数器减1
}
}
});
thread1.start();
thread2.start();
c.await();//在此处等待,当计数器减到0时,才不会阻塞当前线程,继续往下执行
System.out.println( "任务完成,可以下班了");
}
}
CountDownLatch的构造参数接受一个int类型的参数作为计数器,如果想N个线程完成,就传入N。当调用countDown方法时,N就会减1,await方法会阻塞当前线程,直到N变为0.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。