生活随笔
收集整理的這篇文章主要介紹了
测试并发应用 (一)监控Lock接口
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
聲明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 譯者:鄭玉婷 ?
校對(duì):方騰飛
監(jiān)控Lock接口
Lock 接口是Java 并發(fā) API提供的最基本的機(jī)制來同步代碼塊。它允許定義臨界區(qū)。臨界區(qū)是代碼塊可以共享資源,但是不能被多個(gè)線程同時(shí)執(zhí)行。此機(jī)制是通過Lock 接口和 ReentrantLock 類實(shí)現(xiàn)的。
在這個(gè)指南,你將學(xué)習(xí)從Lock對(duì)象可以獲取的信息和如何獲取這些信息。
準(zhǔn)備
指南中的例子是使用Eclipse IDE 來實(shí)現(xiàn)的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打開并創(chuàng)建一個(gè)新的java項(xiàng)目。
怎么做呢…
按照這些步驟來實(shí)現(xiàn)下面的例子:
| 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; |
| 008 | //1.?? 創(chuàng)建一個(gè)類,名為 MyLock ,擴(kuò)展 ReentrantLock 類。 |
| 009 | public class MyLock extends ReentrantLock { |
| 011 | ????// 2. 實(shí)現(xiàn) getOwnerName() 方法。此方法使用Lock類的保護(hù)方法 getOwner(), 返回控制鎖的線程(如果存在)的名字。 |
| 012 | ????public String getOwnerName() { |
| 013 | ????????if (this.getOwner() == null) { |
| 014 | ????????????return "None"; |
| 016 | ????????return this.getOwner().getName(); |
| 019 | ????// 3. 實(shí)現(xiàn) getThreads() 方法。此方法使用Lock類的保護(hù)方法 getQueuedThreads(),返回在鎖里的線程的 queued |
| 021 | ????public Collection<Thread> getThreads() { |
| 022 | ????????return this.getQueuedThreads(); |
| 025 | ????// 4. 創(chuàng)建一個(gè)類,名為 Task,實(shí)現(xiàn) Runnable 接口. |
| 026 | ????public class Task implements Runnable { |
| 028 | ????????// 5. 聲明一個(gè)私有 Lock 屬性,名為 lock。 |
| 029 | ????????private Lock lock; |
| 031 | ????????// 6. 實(shí)現(xiàn)類的構(gòu)造函數(shù),初始化它的屬性值。 |
| 032 | ????????public Task(Lock lock) { |
| 033 | ????????????this.lock = lock; |
| 036 | ????????// 7. 實(shí)現(xiàn) run() 方法。創(chuàng)建迭代5次的for循環(huán)。 |
| 038 | ????????public void run() { |
| 039 | ????????????for (int i = 0; i < 5; i++) { |
| 041 | ????????????????// 8. 使用lock()方法獲取鎖,并打印一條信息。 |
| 042 | ????????????????lock.lock(); |
| 043 | ????????????????System.out.printf("%s: Get the Lock.\n", Thread.currentThread() |
| 044 | ????????????????????????.getName()); |
| 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(); |
| 060 | ????// 10. 創(chuàng)建例子的主類通過創(chuàng)建一個(gè)類,名為 Main 并添加 main()方法。 |
| 061 | ????public static void main(String[] args) throws Exception { |
| 063 | ????????// 11. 創(chuàng)建 MyLock 對(duì)象,名為 lock。 |
| 064 | ????????MyLock lock = new MyLock(); |
| 066 | ????????// 12. 創(chuàng)建有5個(gè)Thread對(duì)象的 array。 |
| 067 | ????????Thread threads[] = new Thread[5]; |
| 069 | ????????// 13. 創(chuàng)建并開始5個(gè)線程來執(zhí)行5個(gè)Task對(duì)象。 |
| 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(); |
| 076 | ????????// 14. 創(chuàng)建迭代15次的for循環(huán)。 |
| 077 | ????????for (int i = 0; i < 15; i++) { |
| 079 | ????????????// 15. 把鎖的擁有者的名字寫入操控臺(tái)。 |
| 080 | ????????????System.out.printf("Main: Logging the Lock\n"); |
| 081 | ????????????System.out.printf("************************\n"); |
| 082 | ????????????System.out.printf("Lock: Owner : %s\n", lock.getOwnerName()); |
| 084 | ????????????// 16. 顯示鎖queued的線程的號(hào)碼和名字。 |
| 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()); |
| 095 | ????????????????System.out.printf("\n"); |
| 098 | ????????????// 17. 顯示關(guān)于Lock對(duì)象的公平性和狀態(tài)的信息。 |
| 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"); |
| 103 | ????????????// 18. 讓線程休眠1秒,并合上類的循環(huán)。 |
| 104 | ????????????TimeUnit.SECONDS.sleep(1); |
它是如何工作的…
在這個(gè)指南里,你實(shí)現(xiàn)的MyLock類擴(kuò)展了ReentrantLock類來返回信息,除此之外獲得不到這些信息 ,因?yàn)镽eentrantLock 類里的數(shù)據(jù)都是保護(hù)類型的。 通過MyLock類實(shí)現(xiàn)的方法:
- getOwnerName():只有唯一一個(gè)線程可以執(zhí)行被Lock對(duì)象保護(hù)的臨界區(qū)。鎖存儲(chǔ)了正在執(zhí)行臨界區(qū)的線程。此線程會(huì)被ReentrantLock類的保護(hù)方法 getOwner()返回。 此方法使用 getOwner() 方法來返回線程的名字。
- getThreads():當(dāng)線程正在執(zhí)行臨界區(qū)時(shí),其他線程嘗試進(jìn)入臨界區(qū)就會(huì)被放到休眠狀態(tài)一直到他們可以繼續(xù)執(zhí)行為止。ReentrantLock類保護(hù)方法getQueuedThreads() 返回 正在等待執(zhí)行臨界區(qū)的線程list。此方法返回 getQueuedThreads() 方法返回的結(jié)果。
我們還使用了 ReentrantLock 類里實(shí)現(xiàn)的其他方法:
- hasQueuedThreads():此方法返回 Boolean 值表明是否有線程在等待獲取此鎖
- getQueueLength(): 此方法返回等待獲取此鎖的線程數(shù)量
- isLocked(): 此方法返回 Boolean 值表明此鎖是否為某個(gè)線程所擁有
- isFair(): 此方法返回 Boolean 值表明鎖的 fair 模式是否被激活
更多…
ReentrantLock 類還有其他方法也是用來獲取Lock對(duì)象的信息的:
- getHoldCount(): 返回當(dāng)前線程獲取鎖的次數(shù)
- isHeldByCurrentThread(): 返回 Boolean 值,表明鎖是否為當(dāng)前線程所擁有
總結(jié)
以上是生活随笔為你收集整理的测试并发应用 (一)监控Lock接口的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。