测试并发应用 (一)监控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

目录
相关文章
|
22天前
|
敏捷开发 测试技术 持续交付
探索自动化测试在敏捷开发中的应用与挑战
本文深入探讨了自动化测试在现代软件开发流程,特别是敏捷开发环境中的重要作用和面临的挑战。通过分析自动化测试的基本原理、实施策略以及在实际项目中的应用案例,揭示了其在提高软件质量和加速产品交付方面的巨大潜力。同时,文章也指出了自动化测试实施过程中可能遇到的技术难题、成本考量及团队协作问题,并提出了相应的解决策略,为软件开发团队提供了有价值的参考和指导。
|
27天前
|
编解码 测试技术 开发工具
测试 iPhone 应用在不同屏幕尺寸和分辨率下的响应式效果
【10月更文挑战第23天】测试 iPhone 应用在不同屏幕尺寸和分辨率下的响应式效果是确保应用质量和用户体验的重要环节。通过手动测试、自动化测试、视觉效果评估、性能测试、用户体验测试等多种方法的综合运用,能够全面地发现应用在响应式效果方面存在的问题,并及时进行解决和优化。同时,持续的测试和优化也是不断提升应用质量和用户满意度的关键。
|
11天前
|
自然语言处理 安全 测试技术
基于大模型的应用的测试的一些注意事项
大模型应用测试需注意三大冲突:时间敏感性冲突,即模型数据可能随时间变得过时;数据真实性冲突,指训练数据中可能存在虚假信息,影响模型准确性;数据一致性冲突,表现为模型对语义相同但句法不同的输入反应不一。测试时应针对这些问题设计用例,确保模型性能。
39 4
|
15天前
|
JSON Java 测试技术
SpringCloud2023实战之接口服务测试工具SpringBootTest
SpringBootTest同时集成了JUnit Jupiter、AssertJ、Hamcrest测试辅助库,使得更容易编写但愿测试代码。
49 3
|
24天前
|
前端开发 数据管理 测试技术
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第27天】本文介绍了前端自动化测试中Jest和Cypress的实战应用与最佳实践。Jest适合React应用的单元测试和快照测试,Cypress则擅长端到端测试,模拟用户交互。通过结合使用这两种工具,可以有效提升代码质量和开发效率。最佳实践包括单元测试与集成测试结合、快照测试、并行执行、代码覆盖率分析、测试环境管理和测试数据管理。
42 2
|
24天前
|
Web App开发 定位技术 iOS开发
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
Playwright 是一个强大的工具,用于在各种浏览器上测试应用,并模拟真实设备如手机和平板。通过配置 `playwright.devices`,可以轻松模拟不同设备的用户代理、屏幕尺寸、视口等特性。此外,Playwright 还支持模拟地理位置、区域设置、时区、权限(如通知)和配色方案,使测试更加全面和真实。例如,可以在配置文件中设置全局的区域设置和时区,然后在特定测试中进行覆盖。同时,还可以动态更改地理位置和媒体类型,以适应不同的测试需求。
24 1
|
25天前
|
前端开发 JavaScript 数据可视化
前端自动化测试:Jest与Cypress的实战应用与最佳实践
【10月更文挑战第26天】前端自动化测试在现代软件开发中至关重要,Jest和Cypress分别是单元测试和端到端测试的流行工具。本文通过解答一系列问题,介绍Jest与Cypress的实战应用与最佳实践,帮助开发者提高测试效率和代码质量。
32 2
|
1月前
|
监控 测试技术 持续交付
掌握跨平台测试策略:确保应用的无缝体验
【10月更文挑战第14天】在多元化设备和操作系统的今天,跨平台测试策略成为确保应用质量和性能的关键。本文探讨了跨平台测试的重要性、核心优势及实施步骤,涵盖Web、移动和桌面应用的测试方法,帮助开发者提高应用的无缝体验。
|
1月前
|
机器学习/深度学习 人工智能 自然语言处理
探索AI在软件测试中的创新应用与实践###
本文旨在探讨人工智能(AI)技术如何革新软件测试领域,提升测试效率、质量与覆盖范围。通过深入分析AI驱动的自动化测试工具、智能化缺陷预测模型及持续集成/持续部署(CI/CD)流程优化等关键方面,本研究揭示了AI技术在解决传统软件测试痛点中的潜力与价值。文章首先概述了软件测试的重要性和当前面临的挑战,随后详细介绍了AI技术在测试用例生成、执行、结果分析及维护中的应用实例,并展望了未来AI与软件测试深度融合的趋势,强调了技术伦理与质量控制的重要性。本文为软件开发与测试团队提供了关于如何有效利用AI技术提升测试效能的实践指南。 ###
|
1月前
|
机器学习/深度学习 弹性计算 自然语言处理
前端大模型应用笔记(二):最新llama3.2小参数版本1B的古董机测试 - 支持128K上下文,表现优异,和移动端更配
llama3.1支持128K上下文,6万字+输入,适用于多种场景。模型能力超出预期,但处理中文时需加中英翻译。测试显示,其英文支持较好,中文则需改进。llama3.2 1B参数量小,适合移动端和资源受限环境,可在阿里云2vCPU和4G ECS上运行。
下一篇
无影云桌面