java线程中锁存器CountDownLatch的使用

CountDownLatch类是一个同步计数器,构造时传入int参数,该参数就是计数器的初始值,每调用一次countDown()方法,计数器减1,计数器大于0 时,await()方法会阻塞程序继续执行。CountDownLatch可以看作是一个倒计数的锁存器,当计数减至0时触发特定的事件。利用这种特性,可以让主线程等待子线程的结束。下面以一个模拟运动员比赛的例子加以说明。

 CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。

1 
import
 java.util.concurrent.CountDownLatch;

2 
 
import
 java.util.concurrent.Executor;

3 
 
import
 java.util.concurrent.ExecutorService;

4 
 
import
 java.util.concurrent.Executors;

5 


6 
 
public
 
class
 CountDownLatchDemo {

7 

private
 
static
 
final
 
int
 PLAYER_AMOUNT 
=
 
5
;

8 

public
 CountDownLatchDemo() {

9 

//
 TODO Auto-generated constructor stub 


10 
 
 }

11 

/**


12 

@param
 args

13 

*/


14 

public
 
static
 
void
 main(String[] args) {

15 

//
 TODO Auto-generated method stub

16 

//
对于每位运动员,CountDownLatch减1后即结束比赛


17 

CountDownLatch begin 
=
 
new
 CountDownLatch(
1
);

18 

//
对于整个比赛,所有运动员结束后才算结束


19 

CountDownLatch end 
=
 
new
 CountDownLatch(PLAYER_AMOUNT);

20 
Player[] plays 
=
 
new
 Player[PLAYER_AMOUNT];

21 


22 

for
(
int
 i
=
0
;i
<
PLAYER_AMOUNT;i
++
)

23 
plays[i] 
=
 
new
 Player(i
+
1
,begin,end);

24 


25 

//
设置特定的线程池,大小为5


26 

ExecutorService exe 
=
 Executors.newFixedThreadPool(PLAYER_AMOUNT);

27 

for
(Player p:plays)

28 
exe.execute(p); 
//
分配线程


29 

System.out.println(

Race begins!

);

30 
begin.countDown();

31 

try
{

32 
end.wait(); 
//
等待end状态变为0,即为比赛结束


33 

}
catch
 (InterruptedException e) {

34 

//
 TODO: handle exception


35 

e.printStackTrace();

36 
}
finally
{

37 
System.out.println(

Race ends!

);

38 
}

39 
exe.shutdown();

40 
}

41 
}

《java线程中锁存器CountDownLatch的使用》

接下来是Player类

注:countDown最好是在finally里面调用

《java线程中锁存器CountDownLatch的使用》
1 
import
 java.util.concurrent.CountDownLatch;

2 


3 


4 

public
 
class
 Player 
implements
 Runnable {

5 


6 

private
 
int
 id;

7 

private
 CountDownLatch begin;

8 

private
 CountDownLatch end;

9 

public
 Player(
int
 i, CountDownLatch begin, CountDownLatch end) {

10 

//
 TODO Auto-generated constructor stub


11 


super
();

12 

this
.id 
=
 i;

13 

this
.begin 
=
 begin;

14 

this
.end 
=
 end;

15 
}

16 


17 
@Override

18 

public
 
void
 run() {

19 

//
 TODO Auto-generated method stub


20 


try
{

21 
begin.await(); 
//
等待begin的状态为0


22 

Thread.sleep((
long
)(Math.random()
*
100
)); 
//
随机分配时间,即运动员完成时间


23 

System.out.println(

Play

+
id
+

 arrived.

);

24 
}
catch
 (InterruptedException e) {

25 

//
 TODO: handle exception


26 

e.printStackTrace();

27 
}
finally
{

28 
end.countDown(); 
//
使end状态减1,最终减至0


29 

}

30 
}

31 
}
《java线程中锁存器CountDownLatch的使用》

下面是张孝祥老师所举例子的程序代码和运行结果:

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

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 (InterruptedException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   };
   service.execute(runnable);
  }
  try {
   System.out.println(“线程”+Thread.currentThread().getName()+”即将发布命令”);
   cdOrder.countDown();
   System.out.println(“线程”+Thread.currentThread().getName()+”已接受命令,正在等待结果”);
   cdAnswer.await();
   Thread.sleep((long)(Math.random()*10000));
   System.out.println(“线程”+Thread.currentThread().getName()+”已收到所有响应结果”);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  service.shutdown();
 }
}
运行结果:

线程pool-1-thread-1正准备接受命令
线程pool-1-thread-2正准备接受命令
线程pool-1-thread-3正准备接受命令
线程main即将发布命令
线程main已接受命令,正在等待结果
线程pool-1-thread-2已接受命令
线程pool-1-thread-1已接受命令
线程pool-1-thread-3已接受命令
线程pool-1-thread-2回应命令处理结果
线程pool-1-thread-1回应命令处理结果
线程pool-1-thread-3回应命令处理结果
线程main已收到所有响应结果

    原文作者:java锁
    原文地址: https://blog.csdn.net/chenleixing/article/details/42173593
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞