使用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,使得当所有的线程都执行完毕后,我们可以统计出所有线程对笔者网站进行访问所消耗的时间.

  

posted @ 2014-09-02 09:41  小豆灵师  阅读(402)  评论(0编辑  收藏  举报