java同步工具類之CountDownLatch
來源:程序員人生 發布時間:2015-05-12 09:19:37 閱讀次數:3895次
在1些利用場合中,某段程序需要等待某個條件到達要求后才能履行,或等待1定長的時間后此行,從jdk1.5開始就能夠使用CountDownLatch實現,
CountDownLatch類是1個同步倒數計數器,構造時傳入int參數,該參數就是計數器的初始值,每調用1次countDown()方法,計數器減1,計數器大于0 時,await()方法會阻塞后面程序履行,直到計數器為0。
public class CountdownLatchTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
final CountDownLatch cdAnswer = new CountDownLatch(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
System.out.println("線程" + Thread.currentThread().getName() +
"正準備接受命令");
cdOrder.await();
System.out.println("線程" + Thread.currentThread().getName() +
"已接受命令");
Thread.sleep((long)(Math.random()*10000));
System.out.println("線程" + Thread.currentThread().getName() +
"回應命令處理結果");
cdAnswer.countDown();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try {
Thread.sleep((long)(Math.random()*10000));
System.out.println("線程" + Thread.currentThread().getName() +
"行將發布命令");
cdOrder.countDown();
System.out.println("線程" + Thread.currentThread().getName() +
"已發送命令,正在等待結果");
cdAnswer.await();
System.out.println("線程" + Thread.currentThread().getName() +
"已收到所有響應結果");
} catch (Exception e) {
e.printStackTrace();
}
service.shutdown();
}
}
上面示例初始化兩個CountDownLatch示例,分外傳入初始值1和3,cdOrder.await()后面的代碼,將會被阻塞,直到調用1次cdOrder.countDown()后才向下履行;cdAnswer.await()后面代碼阻塞,調用3次cdAnswer.countDown()向下履行。
所以上面履行結果:
線程pool⑴-thread⑴正準備接受命令
線程pool⑴-thread⑶正準備接受命令
線程pool⑴-thread⑵正準備接受命令
線程main行將發布命令
線程main已發送命令,正在等待結果
線程pool⑴-thread⑴已接受命令
線程pool⑴-thread⑵已接受命令
線程pool⑴-thread⑶已接受命令
線程pool⑴-thread⑵回應命令處理結果
線程pool⑴-thread⑶回應命令處理結果
線程pool⑴-thread⑴回應命令處理結果
線程main已收到所有響應結果

await(long timeout, TimeUnit unit),是等待1定時間,然后履行,不管計數器是不是到0了。
下面例子來源:http://www.blogjava.net/freeman1984/archive/2011/07/04/353654.html
10個同學上車,車等待同學上車,如果有等待時間限制,到時間就開走,不管學生上沒上完。如果沒有等待時間,學生上完了再開:
public class CountDownLatchTest {
public static int numberOfPeople = 10;//等車的學生數
public static boolean isGone = false;//車開的標志
public static int carWaitTime = 3;//車等的時間
public static void main(String[] args) throws InterruptedException {
CountDownLatch waitStudentsGetOn = new CountDownLatch(numberOfPeople);
new Thread(new GetOn(waitStudentsGetOn)).start();
waitStudentGetOn(waitStudentsGetOn);//等所有的學生上車
driveHome();//開車走
}
private static void waitStudentGetOn(CountDownLatch waitStudentsGetOn) throws InterruptedException {
System.out.println("趕快的,抓緊時間上車..");
waitStudentsGetOn.await(carWaitTime, TimeUnit.SECONDS);//等5秒,還沒上車,就開走。。
}
private static void driveHome() throws InterruptedException {
System.out.println("開車,鞋兒破 帽兒破 身上的袈裟破 你笑我 他笑我 1把扇兒破");
isGone = true;
}
}
class GetOn implements Runnable{
private CountDownLatch waitStudentsGetOn;
GetOn(CountDownLatch waitStudentsGetOn){
this.waitStudentsGetOn = waitStudentsGetOn;
}
public void run() {
for (int i = 0; i < CountDownLatchTest.numberOfPeople; i++) {
try {
if(CountDownLatchTest.isGone){
System.out.println("媽的,還差:"+waitStudentsGetOn.getCount()+" 個沒娃上車呢.怎樣車走了");
break;
}
boolean goonSuccess = new Student(i+1).getOn();//順序上車
if(goonSuccess)waitStudentsGetOn.countDown();
} catch (InterruptedException e) {}
if(waitStudentsGetOn.getCount()!=0l){
System.out.println("還差:"+(waitStudentsGetOn.getCount())+" 個沒上車");
}else{
System.out.println("都上車了");
}
}
}
class Student{
private int myNum;//學生編號
public Student(int num){
this.myNum = num;
}
//上車
public boolean getOn() throws InterruptedException{
Thread.currentThread().sleep(new Random().nextInt(2)*1000);//上車使用的時間,隨機
if(CountDownLatchTest.isGone){
return false;//不能上了,上車失敗
}
System.out.print("編號為:"+myNum+"的同學上車了..");
return true;
}
}
}
‘
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈