zoukankan      html  css  js  c++  java
  • 使用java闭锁实现并发

    闭锁:一个同步辅助类,在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。即,一组线程等待某一事件发生,事件没有发生前,所有线程将阻塞等待;而事件发生后,所有线程将开始执行;闭锁最初处于封闭状态,当事件发生后闭锁将被打开,一旦打开,闭锁将永远处于打开状态。

     1 import java.io.BufferedReader;
     2 import java.io.IOException;
     3 import java.io.InputStream;
     4 import java.io.InputStreamReader;
     5 import java.net.URL;
     6 import java.net.URLConnection;
     7 import java.util.ArrayList;
     8 import java.util.List;
     9 import java.util.concurrent.CountDownLatch;
    10 
    11 public class ThreadTest {
    12     public static void main(String[] args) {
    13         final int num = 10;
    14         //CountDownLatch是一种灵活的闭锁实现,闭锁状态包括一个计数器,该计数器被初始化一个正数,表示需要等待的事件数量。
    15         final CountDownLatch begin = new CountDownLatch(1);
    16         final CountDownLatch end = new CountDownLatch(num);
    17         for (int i = 0; i < num; i++) {
    18             new Thread(new MyWorker(i, begin, end)).start();
    19         }
    20         // 睡眠十秒,等所有线程都准备好之后再启动并发测试
    21         try {
    22             Thread.sleep(10000);
    23         } catch (InterruptedException e1) {
    24             e1.printStackTrace();
    25         }
    26         System.out.println("开始进行并发测试");
    27         //调用countDown 方法递减计算器,表示有一个事件已经发生了
    28         begin.countDown();
    29         long startTime = System.currentTimeMillis();
    30         try {
    31             //await方法要一直阻塞直到计数器为零,或者等待的线程中断、超时
    32             end.await();
    33         } catch (InterruptedException e) {
    34             e.printStackTrace();
    35         } finally {
    36             long endTime = System.currentTimeMillis();
    37             System.out.println("结束并发测试 !");
    38             System.out.println("花费时间: " + (endTime - startTime));
    39         }
    40     }
    41 }
    42 
    43 class MyWorker implements Runnable {
    44     final CountDownLatch begin;
    45     final CountDownLatch end;
    46     final int id;
    47 
    48     public MyWorker(final int id, final CountDownLatch begin,
    49             final CountDownLatch end) {
    50         this.id = id;
    51         this.begin = begin;
    52         this.end = end;
    53     }
    54 
    55     @Override
    56     public void run() {
    57         try {
    58             System.out.println(this.id + " ready !");
    59             //await方法要一直阻塞直到计数器为零,或者等待的线程中断、超时
    60             begin.await();
    61             // execute your logic
    62             URLConnection webUrlRequest = request("http://the090303.com");
    63             List<String> readline = readLine(webUrlRequest.getInputStream());
    64 //            System.out.println(readline);
    65             Thread.sleep((long) (Math.random() * 10000));
    66         } catch (Throwable e) {
    67             e.printStackTrace();
    68         } finally {
    69             System.out.println(this.id + " 完成测试 !");
    70             //调用countDown 方法递减计算器,表示有一个事件已经发生了
    71             end.countDown();
    72         }
    73     }
    74 
    75     public static URLConnection request(String requestUrl) throws IOException {
    76         return new URL(requestUrl).openConnection();
    77     }
    78 
    79     public static List<String> readLine(InputStream inputStream)
    80             throws IOException {
    81         List<String> list = new ArrayList<String>();
    82         BufferedReader bufferReader = null;
    83         try {
    84             bufferReader = new BufferedReader(
    85                     new InputStreamReader(inputStream));
    86             String readline;
    87             while ((readline = bufferReader.readLine()) != null) {
    88                 list.add(readline);
    89             }
    90         } finally {
    91             bufferReader.close();
    92         }
    93         return list;
    94     }
    95 }

    上面CountDownLatch是一种灵活的闭锁实现,闭锁状态包括一个计数器,该计数器被初始化一个正数,表示需要等待的事件数量。调用countDown 方法递减计算器,表示有一个事件已经发生了,而await方法要一直阻塞直到计数器为零,或者等待的线程中断、超时.所以上面用两个闭锁来实现一个起始门(begin)跟结束门(end),起始门计数器初始值为1,结束门计算器初始值为线程数量,每个线程就是在起始门等待,所以这样确保实现真正并发,而每个线程在最后做的一件事情是调用结束门(end)的countDown方法减1,使得当所有的线程都执行完毕后,我们可以统计出所有线程对笔者网站进行访问所消耗的时间.

      

  • 相关阅读:
    运算符
    练习
    JAVA学习日报 9/23
    JAVA学习日报 8.22
    JAVA学习日报 8.21
    第一节:SpringMVC 处理请求数据【1】
    第六节:@RequestMapping 映射请求占位符 @PathVariable 注解
    第一节:REST 风格的URL地址约束
    第二节:REST风格的案例及源码分析
    (一)IOC 容器:【1】@Configuration&@Bean 给容器中注册组件
  • 原文地址:https://www.cnblogs.com/lnluckybamboo/p/3950777.html
Copyright © 2011-2022 走看看