测试并发应用 (一)监控Lock接口-阿里云开发者社区

开发者社区> boxti> 正文

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

简介:
+关注继续查看

声明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: 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<Thread> 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<Thread> 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 值,表明锁是否为当前线程所拥有

参见

第二章,基本线程同步: 使用lock同步代码块
第七章,自定义同步类: 实现自定义锁

文章转自 并发编程网-ifeve.com

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
Java多线程高并发学习笔记(二)——深入理解ReentrantLock与Condition
锁的概念 从jdk发行1.5版本之后,在原来synchronize的基础上,增加了重入锁ReentrantLock。 本文就不介绍synchronize了,有兴趣的同学可以去了解一下,本文重点介绍ReentrantLock。
1068 0
Centos7下Docker上部署webgoat(用来演示Web应用程序中的典型安全漏洞的应用程序)
Centos7下Docker上部署webgoat(用来演示Web应用程序中的典型安全漏洞的应用程序)
652 0
Web防火墙应用场景:短信接口防刷
很多站长发现网站服务器变卡,短信注册接口费用大量增长,甚至注册用户被竞争对手精确营销,客户流失。 这是什么情况? 且听我们慢慢道来:
10735 0
【转】自动实时监控Windows2003服务器终端登录并发邮件和发短信通知
记得以前管理的一批windows服务器,一些开源程序做的web站点总会遭到入侵。然而就想找找看有没有办法可以知道服务器有没有被入侵。服务器在什么时候登陆过,如果登陆马上发邮件通知,感觉这种问题肯定有人处理过,于是网上搜罗了一下。
1111 0
Java面向对象高级--抽象类与接口的应用
<h1>1、为抽象类和接口实例化</h1> <div> <img src="http://img.blog.csdn.net/20130928113110421" alt=""><br> </div> <div>抽象类和接口不能直接实例化,因为其内部包含了各个抽象方法,抽象方法本身都是未实现的方法,所以无法调用。通过对象多态性,子类发生了向上转型之后,所调用的全部方法都是被覆写过了的方
1297 0
+关注
boxti
12535
10037
文章
1327
问答
文章排行榜
最热
最新
相关电子书
更多
《Nacos架构&原理》
立即下载
《看见新力量:二》电子书
立即下载
云上自动化运维(CloudOps)白皮书
立即下载