您的位置:首页 > 编程语言 > Java开发

Java中CountDownLatch的使用和求多线程的运行时间

2018-03-02 23:34 731 查看

一、CountDownLatch的API

构造方法摘要
构造方法
Constructor and Description
CountDownLatch(int count)
构造一个以给定计数 
CountDownLatch
 CountDownLatch。
方法摘要所有方法 接口方法 具体的方法
Modifier and TypeMethod and Description
void
await()
导致当前线程等到锁存器计数到零,除非线程是 interrupted 。
boolean
await(long timeout, TimeUnit unit)
使当前线程等待直到锁存器计数到零为止,除非线程为 interrupted或指定的等待时间过去。
void
countDown()
减少锁存器的计数,如果计数达到零,释放所有等待的线程。
long
getCount()
返回当前计数。
String
toString()
返回一个标识此锁存器的字符串及其状态。
 可以看到 CountDownLatch 类有两个最重要的方法countDown()   让计数值-1await()               阻塞线程,直到计数值为0才唤醒计数值最小为0 通过一个简单的例子可以验证上面的观点,不使用线程即可测试1public static void main(String args[]) throws InterruptedException {

        final CountDownLatch latch = new CountDownLatch(5);//设置计数值为5

        System.out.println("开始你的表演!");

        for(int i=0;i<3;i++) {
            latch.countDown();
            System.out.println("latch.getCount:"+latch.getCount());
        }

        latch.await();
        System.out.println("再见吧,大海!");
    }
运行结果如下

可见,当计数值为2的时候,遇到了 await(),此后将会一直处于等待状态(看左侧的红色按钮,表示程序还在等待)测试2public static void main(String args[]) throws InterruptedException {

    final CountDownLatch latch = new CountDownLatch(5);//设置计数值为5

    System.out.println("开始你的表演!");

    for(int i=0;i<8;i++) {
        latch.countDown();
        System.out.println("latch.getCount:"+latch.getCount());
    }

    latch.await();
    System.out.println("再见吧,大海!");
}
还是上面的代码,我们把 3 改成一个更大点的数,比如8运行结果如下

结果说明,当计数值为0时,await()才会继续执行,而不会等待同时,也发现计数值最小值为 0 

二、求多线程的运行时间

CountDownLatch 允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。这里我们可以实现一个功能,就是 “统计多线程的执行时间”,因为我们需要判断多线程是什么时候 start的,什么时候 end 的。而正好 CountDownLatch 类可以帮助我们知道什么时候结束。让我们一步步实现它!1、如何计算某段代码的运行时间public static void main(String args[]) {

    long startTime = System.currentTimeMillis();
    for(int i=0;i<1000;i++) {
        System.out.println(i);
    }
    long endTime = System.currentTimeMillis();

    System.out.println((endTime-startTime)+"ms");//13ms
}
通过 System.currentTimeMillis() 方法获得当前系统时间(单位ms) 下面我们来求多线程的执行时间2、失败的例子public static void main(String args[]) {

      System.out.println("主线程开始");

      long startTime = System.currentTimeMillis();
      for(int i=0;i<5;i++) {
          new Thread() {
              @Override
              public void run() {
                  System.out.println(currentThread().getName()+"开始执行..");
                  try {
                      sleep(1000);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
                  System.out.println(currentThread().getName()+"结束执行..");
              }
          }.start();
      }
      long endTime = System.currentTimeMillis();

      System.out.println("多线程运行时间:"+(endTime-startTime)+"ms");//2ms

      System.out.println("主线程结束");
  }
运行结果如下

很显然,这是一个失败的答案。因为我们知道多线程(包括main线程)是抢占CPU执行资源的,所以一旦几个线程处于就绪状态的话,都有机会抢到执行的机会。所以,我们的两处求系统时间的地方都是我们不希望的时间。也就是说,我们希望结果应该是这样的,“主线程开始”-->5个子线程执行-->“主线程结束”。 3、成功的例子public static void main(String args[]) throws InterruptedException {

     CountDownLatch latch = new CountDownLatch(5);//设置计数值

     System.out.println("主线程开始");

     long startTime = System.currentTimeMillis();
     for(int i=0;i<5;i++) {
         new Thread() {
             @Override
             public void run() {
                 System.out.println(currentThread().getName()+"开始执行..");
                 try {
                     sleep(1000);
                 } catch (InterruptedException e) {
                     e.printStackTrace();
                 }
                 System.out.println(currentThread().getName()+"结束执行..");
                 latch.countDown();
             }
         }.start();
     }

     latch.await();

     long endTime = System.currentTimeMillis();

     System.out.println("多线程运行时间:"+(endTime-startTime)+"ms");//1007ms

     System.out.println("主线程结束");
 }
运行结果如下

这次是结果是我们想要的。同时,我们也看到了,5个线程,每个线程需要执行 1s (停止 1s),最终 5 个线程全部执行,只需要1s多点,而不是 5s,这就是多线程的作用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: