在Java中有个类是CountDownLatch。这是一个工具类,是用于同步线程的。
这个类的大致作用是:当一个主线程需要等待其他线程完成任务之后,才能接着往下执行。
此时CountDownLatch对象调用了一个await()方法等待需要完成的进程执行完,主线程才能接着往下走。
下面是Demo演示类,代码的思路是:
主线程的等待两个Worker对象完成工作,才能继续往下执行。
而countDownLatch类的构造方法传入一个int值。
其值意味着与CountDownLatch对象关联的线程数的个数。
每个线程的run方法执行完毕之后,调用CountDownLatch的countDown()方法让计数减一。知道技术为0,主线程就认为自己等待的线程均已完成任务,可以往下执行了。
下面的demo构造了两个worker对象。一个工作3秒,另一个工作10秒。当两个工作线程启动,即刻调用了CountDownLatch的await()方法。当计数为0,主线程才可以接着往下走。
package hello;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
public class CountDownLatchTest
{
public static void main(String[] args) throws InterruptedException
{
/**
* 构造方法参数表示有两个线程在执行任务,每个线程任务执行完成后,调用countDown()方法使计数减一,直到计数减为0,主线程才往下执行。
*/
CountDownLatch countDownLatch = new CountDownLatch( 2 );
Worker zhangsan = new Worker( "张三", 3000, countDownLatch );
Worker lisi = new Worker( "李四", 10000, countDownLatch );
Thread zhangsanThread = new Thread( zhangsan );
Thread lisiThread = new Thread( lisi );
zhangsanThread.start();
lisiThread.start();
/**
*在两个线程启动后,countDownLatch对象要调用await方法,每次一个线程的run方法调用完之后,都要调用一个CountDownLatch类的countDown()方法来使计数器减一
*/
countDownLatch.await();
System.out.println( "两个工人都完成了工作" );
}
}
class Worker implements Runnable
{
private String workerName;
private int workTime;
/**
* 每个与CountDownLatch对象关联的线程类,里面应该维护一个CountDownLatch对象引用,
* 因为在run方法执行完之后要调用countDownLatch对象的countDown()方法来使计数减一
*/
private CountDownLatch countDownLatch;
public Worker(String workerName, int workTime, CountDownLatch countDownLatch)
{
this.workerName = workerName;
this.workTime = workTime;
this.countDownLatch = countDownLatch;
}
@Override
public void run()
{
try
{
System.out.println( "工人------>" + this.workerName + "在" + new Date().toLocaleString() + "开始工作..." );
doWork();
System.out.println( "工人------->" + this.workerName + "在" + new Date().toLocaleString() + "完成工作" );
}
catch(Exception e)
{
System.out.println("进入catch字句");
}
finally
{
/**
* run方法执行完,调用countDown()方法使得计数减一
*/
this.countDownLatch.countDown();
}
}
public void doWork()
{
try
{
Thread.sleep( workTime );
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
}