测试并发应用 (一)监控Lock接口

声明:本文是《 Java 7 Concurrency Cookbook》的第八章, 作者: Javier Fernández González 译者:郑玉婷  

校对:方腾飞

监控Lock接口

Lock 接口是Java 并发 API提供的最基本的机制来同步代码块。它允许定义临界区。临界区是代码块可以共享资源,但是不能被多个线程同时执行。此机制是通过Lock 接口和 ReentrantLock 类实现的。

在这个指南,你将学习从Lock对象可以获取的信息和如何获取这些信息。

准备

指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。

怎么做呢…

按照这些步骤来实现下面的例子:

001 package tool;
002  
003 import java.util.Collection;
004 import java.util.concurrent.TimeUnit;
005 import java.util.concurrent.locks.Lock;
006 import java.util.concurrent.locks.ReentrantLock;
007  
008 //1.   创建一个类,名为 MyLock ,扩展 ReentrantLock 类。
009 public class MyLock extends ReentrantLock {
010  
011     // 2. 实现 getOwnerName() 方法。此方法使用Lock类的保护方法 getOwner(), 返回控制锁的线程(如果存在)的名字。
012     public String getOwnerName() {
013         if (this.getOwner() == null) {
014             return "None";
015         }
016         return this.getOwner().getName();
017     }
018  
019     // 3. 实现 getThreads() 方法。此方法使用Lock类的保护方法 getQueuedThreads(),返回在锁里的线程的 queued
020     // list。
021     public Collection<Thread> getThreads() {
022         return this.getQueuedThreads();
023     }
024  
025     // 4. 创建一个类,名为 Task,实现 Runnable 接口.
026     public class Task implements Runnable {
027  
028         // 5. 声明一个私有 Lock 属性,名为 lock。
029         private Lock lock;
030  
031         // 6. 实现类的构造函数,初始化它的属性值。
032         public Task(Lock lock) {
033             this.lock = lock;
034         }
035  
036         // 7. 实现 run() 方法。创建迭代5次的for循环。
037         @Override
038         public void run() {
039             for (int i = 0; i < 5; i++) {
040  
041                 // 8. 使用lock()方法获取锁,并打印一条信息。
042                 lock.lock();
043                 System.out.printf("%s: Get the Lock.\n", Thread.currentThread()
044                         .getName());
045  
046                 // 9. 让线程休眠 500 毫秒。使用 unlock() 释放锁并打印一条信息。
047                 try {
048                     TimeUnit.MILLISECONDS.sleep(500);
049                     System.out.printf("%s: Free the Lock.\n", Thread
050                             .currentThread().getName());
051                 } catch (InterruptedException e) {
052                     e.printStackTrace();
053                 } finally {
054                     lock.unlock();
055                 }
056             }
057         }
058     }
059  
060     // 10. 创建例子的主类通过创建一个类,名为 Main 并添加 main()方法。
061     public static void main(String[] args) throws Exception {
062  
063         // 11. 创建 MyLock 对象,名为 lock。
064         MyLock lock = new MyLock();
065  
066         // 12. 创建有5个Thread对象的 array。
067         Thread threads[] = new Thread[5];
068  
069         // 13. 创建并开始5个线程来执行5个Task对象。
070         for (int i = 0; i < 5; i++) {
071             Task task = lock.new Task(lock);
072             threads[i] = new Thread(task);
073             threads[i].start();
074         }
075  
076         // 14. 创建迭代15次的for循环。
077         for (int i = 0; i < 15; i++) {
078  
079             // 15. 把锁的拥有者的名字写入操控台。
080             System.out.printf("Main: Logging the Lock\n");
081             System.out.printf("************************\n");
082             System.out.printf("Lock: Owner : %s\n", lock.getOwnerName());
083  
084             // 16. 显示锁queued的线程的号码和名字。
085             System.out.printf("Lock: Queued Threads: %s\n",
086                     lock.hasQueuedThreads()); // 译者注:加上 System
087             if (lock.hasQueuedThreads()) {
088                 System.out.printf("Lock: Queue Length: %d\n",
089                         lock.getQueueLength());
090                 System.out.printf("Lock: Queued Threads: ");
091                 Collection<Thread> lockedThreads = lock.getThreads();
092                 for (Thread lockedThread : lockedThreads) {
093                     System.out.printf("%s ", lockedThread.getName());
094                 }
095                 System.out.printf("\n");
096             }
097  
098             // 17. 显示关于Lock对象的公平性和状态的信息。
099             System.out.printf("Lock: Fairness: %s\n", lock.isFair());
100             System.out.printf("Lock: Locked: %s\n", lock.isLocked());
101             System.out.printf("************************\n");
102  
103             // 18. 让线程休眠1秒,并合上类的循环。
104             TimeUnit.SECONDS.sleep(1);
105         }
106     }
107 }

它是如何工作的…

在这个指南里,你实现的MyLock类扩展了ReentrantLock类来返回信息,除此之外获得不到这些信息 ,因为ReentrantLock 类里的数据都是保护类型的。 通过MyLock类实现的方法:

  • getOwnerName():只有唯一一个线程可以执行被Lock对象保护的临界区。锁存储了正在执行临界区的线程。此线程会被ReentrantLock类的保护方法 getOwner()返回。 此方法使用 getOwner() 方法来返回线程的名字。
  • getThreads():当线程正在执行临界区时,其他线程尝试进入临界区就会被放到休眠状态一直到他们可以继续执行为止。ReentrantLock类保护方法getQueuedThreads() 返回 正在等待执行临界区的线程list。此方法返回 getQueuedThreads() 方法返回的结果。

我们还使用了 ReentrantLock 类里实现的其他方法:

  • hasQueuedThreads():此方法返回 Boolean 值表明是否有线程在等待获取此锁
  • getQueueLength(): 此方法返回等待获取此锁的线程数量
  • isLocked(): 此方法返回 Boolean 值表明此锁是否为某个线程所拥有
  • isFair(): 此方法返回 Boolean 值表明锁的 fair 模式是否被激活

更多…

ReentrantLock 类还有其他方法也是用来获取Lock对象的信息的:

  • getHoldCount(): 返回当前线程获取锁的次数
  • isHeldByCurrentThread(): 返回 Boolean 值,表明锁是否为当前线程所拥有
时间: 2024-08-30 00:40:20

测试并发应用 (一)监控Lock接口的相关文章

第八章- 测试并发应用(引言)

声明:本文是< Java 7 Concurrency Cookbook>的第八章, 作者: Javier Fernández González 译者:郑玉婷 8 测试并发应用 章节提要: 监控Lock接口 监控Phaser类 监控执行者框架 监控Fork/Join池 编写有效的日志 FindBugs分析并发代码 配置Eclipse来调试并发代码 配置NetBeans来调试并发代码 MultithreadedTC测试并发代码 介绍 测试应用是很关键的任务.在应用准备好面向最终用户之前,你必须验证

银行取款[多线程]{使用重入锁Lock接口ReentrantLock锁确保线程同步}

经典例子:老婆(朱丽叶)老公(罗密欧),使用银行卡和存折,或者网银等,同时对同一账户操作的安全问题.  此处用多线程实现,同时取款的模拟实现,使用使用Lock接口ReentrantLock锁确保线程同步,查看取款安全隐患问题,代码如下: -----------------------------------------------------------------------------------------------------------------------------------

测试并发应用(六)用 FindBugs 分析并发代码

声明:本文是< Java 7 Concurrency Cookbook>的第八章, 作者: Javier Fernández González 译者:郑玉婷 用 FindBugs 分析并发代码 静态代码分析工具是一套通过分析应用源代码来查找潜在异常的工具.这些工具,例如 Checkstyle, PMD, 或者 FindBugs,他们有定义极好的实践(good practices) 规则,然后解析源代码来查找有没有违反这些规则.目的是在产品运行之前,更早的找到异常或者修改较差性能的代码.各种编程

测试并发应用(八)配置NetBeans来调试并发代码

配置NetBeans来调试并发代码 在当今世界,软件开发的应用必须工作正常,要达到公司的质量标准,还要在将来可以很容易的修改,而且不仅要在有限的时间内,还要尽可能低的费用支出.为了到达这个目标,必需使用 IDE,它集合了一个公共接口和多个工具(编译器和调试器)为了方便应用程序的开发. 如果你使用 Java 编程语言,那么 NetBeans 是最普遍的 IDE之一.它有一个内置调试器(integrated debugger)允许你调试你的应用.在这个指南,你将学习如何改变配置来帮助测试并发应用.

jemeter测试 并发超过200 tomcat不处理请求 jemeter聚合报告卡住没有结果

问题描述 jemeter测试 并发超过200 tomcat不处理请求 jemeter聚合报告卡住没有结果 解决方案

测试并发应用(九)MultithreadedTC测试并发代码

MultithreadedTC测试并发代码 MultithreadedTC 是一个 Java 库用来测试并发应用.它的主要目的是为了解决并发应用的不确定的问题.你不能控制他们的执行顺序.为了这个目睹,它包含了内部节拍器来控制应用的不同线程的执行顺序.这些测试线程作为类的方法来实现的. 在这个指南,你将学习如何使用 MultithreadedTC 库来为LinkedTransferQueue 实现一个测试. 准备 你必须从 http://code.google.com/p/ multithread

测试并发应用(七)配置Eclipse来调试并发代码

声明:本文是< Java 7 Concurrency Cookbook>的第八章, 作者: Javier Fernández González 译者:郑玉婷 校对:方腾飞 配置Eclipse来调试并发代码 当今,几乎全部的程序员,不管使用什么程序语言,都会用IDE来创建应用.在相同的应用里,他们提供了很多有趣的功能来整合,例如: 任务管理 自动生成代码 自动生成文档 与版本控制系统集成 debugger测试应用 创建不同类型的应用和项目 IDE最有用的特点其一就是debugger.你可以一步一

求一款App的网络数据监控(接口的请求频率和数据量)的SDK

问题描述 求一款网络数据监控(接口的请求频率和数据量)的SDK,之前云测的一个版本有过,但是被砍掉了:newrelic,有bug:听云数据不全. 解决方案 帮你问了下,试下oneapm吧

测试并发应用(二)监控Phaser类

声明:本文是< Java 7 Concurrency Cookbook>的第八章, 作者: Javier Fernández González 译者:郑玉婷 监控Phaser类 Java 并发 API 提供的其中一个最复杂且强大的功能是使用 Phaser 类来执行同步phased任务.当有些任务可以分成步骤执行时,此机制是很有用的.Phaser类提供的同步线程机制是在每个步骤的末端, 所以全部的线程都完成第一步后,才能开始执行第二步. 在这个指南,你将学习如何从Phaser类获取其状态信息.