博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
测试并发应用 (一)监控Lock接口
阅读量:6948 次
发布时间:2019-06-27

本文共 3742 字,大约阅读时间需要 12 分钟。

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

校对:方腾飞

监控Lock接口

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

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

准备

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

怎么做呢…

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

package tool;import java.util.Collection;import java.util.concurrent.TimeUnit;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;//1.   创建一个类,名为 MyLock ,扩展 ReentrantLock 类。public class MyLock extends ReentrantLock {	// 2. 实现 getOwnerName() 方法。此方法使用Lock类的保护方法 getOwner(), 返回控制锁的线程(如果存在)的名字。	public String getOwnerName() {		if (this.getOwner() == null) {			return "None";		}		return this.getOwner().getName();	}	// 3. 实现 getThreads() 方法。此方法使用Lock类的保护方法 getQueuedThreads(),返回在锁里的线程的 queued	// list。	public Collection
getThreads() { return this.getQueuedThreads(); } // 4. 创建一个类,名为 Task,实现 Runnable 接口. public class Task implements Runnable { // 5. 声明一个私有 Lock 属性,名为 lock。 private Lock lock; // 6. 实现类的构造函数,初始化它的属性值。 public Task(Lock lock) { this.lock = lock; } // 7. 实现 run() 方法。创建迭代5次的for循环。 @Override public void run() { for (int i = 0; i < 5; i++) { // 8. 使用lock()方法获取锁,并打印一条信息。 lock.lock(); System.out.printf("%s: Get the Lock.\n", Thread.currentThread() .getName()); // 9. 让线程休眠 500 毫秒。使用 unlock() 释放锁并打印一条信息。 try { TimeUnit.MILLISECONDS.sleep(500); System.out.printf("%s: Free the Lock.\n", Thread .currentThread().getName()); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } } } } // 10. 创建例子的主类通过创建一个类,名为 Main 并添加 main()方法。 public static void main(String[] args) throws Exception { // 11. 创建 MyLock 对象,名为 lock。 MyLock lock = new MyLock(); // 12. 创建有5个Thread对象的 array。 Thread threads[] = new Thread[5]; // 13. 创建并开始5个线程来执行5个Task对象。 for (int i = 0; i < 5; i++) { Task task = lock.new Task(lock); threads[i] = new Thread(task); threads[i].start(); } // 14. 创建迭代15次的for循环。 for (int i = 0; i < 15; i++) { // 15. 把锁的拥有者的名字写入操控台。 System.out.printf("Main: Logging the Lock\n"); System.out.printf("************************\n"); System.out.printf("Lock: Owner : %s\n", lock.getOwnerName()); // 16. 显示锁queued的线程的号码和名字。 System.out.printf("Lock: Queued Threads: %s\n", lock.hasQueuedThreads()); // 译者注:加上 System if (lock.hasQueuedThreads()) { System.out.printf("Lock: Queue Length: %d\n", lock.getQueueLength()); System.out.printf("Lock: Queued Threads: "); Collection
lockedThreads = lock.getThreads(); for (Thread lockedThread : lockedThreads) { System.out.printf("%s ", lockedThread.getName()); } System.out.printf("\n"); } // 17. 显示关于Lock对象的公平性和状态的信息。 System.out.printf("Lock: Fairness: %s\n", lock.isFair()); System.out.printf("Lock: Locked: %s\n", lock.isLocked()); System.out.printf("************************\n"); // 18. 让线程休眠1秒,并合上类的循环。 TimeUnit.SECONDS.sleep(1); } }}

它是如何工作的…

在这个指南里,你实现的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 值,表明锁是否为当前线程所拥有

参见

文章转自 

转载地址:http://tirnl.baihongyu.com/

你可能感兴趣的文章
L7 linux shell编程练习
查看>>
开会 顺口溜
查看>>
用PHP和树莓派开发一个比特币/以太坊交易机器人
查看>>
有热备,有事物损坏 薛忠权(ERIKXUE)
查看>>
MySQL入门(二)
查看>>
手把手教 centos+nginx1.3.9+php5.4.9+mysql5.5.28+memcached
查看>>
PHP设计模式(3)观察者模式
查看>>
数据库中的左连接(left join)和右连接(right join)区别
查看>>
spring data jpa 调用oracle 存储过程
查看>>
夺命雷公狗---无限极分类NO4
查看>>
Teams新功能更新【已发布】Teams PowerShell 命令详解
查看>>
我的友情链接
查看>>
Ansible快速开始-指挥集群
查看>>
Java容器详解(以Array Arrays ArrayList为例)
查看>>
Iterator和ListIterator迭代器
查看>>
思科默认 NAT timeout
查看>>
error 1067 (42000) at line 1:Invalid default value for 'id'
查看>>
我的友情链接
查看>>
逻辑DG ORA-16240: Waiting for logfile
查看>>
ORACLE系列脚本3:救命的JOB处理脚本
查看>>