声明:本文是《 Java 7 Concurrency Cookbook 》的第八章, 作者: Javier Fernández González 译者:郑玉婷
校对:方腾飞
监控Lock接口
Lock 接口是Java 并发 API提供的最基本的机制来同步代码块。它允许定义临界区。临界区是代码块可以共享资源,但是不能被多个线程同时执行。此机制是通过Lock 接口和 ReentrantLock 类实现的。
在这个指南,你将学习从Lock对象可以获取的信息和如何获取这些信息。
准备
指南中的例子是使用Eclipse IDE 来实现的。如果你使用Eclipse 或者其他的IDE,例如NetBeans, 打开并创建一个新的java项目。
怎么做呢…
按照这些步骤来实现下面的例子:
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; |
009 | public class MyLock extends ReentrantLock { |
012 | public String getOwnerName() { |
013 | if ( this .getOwner() == null ) { |
016 | return this .getOwner().getName(); |
021 | public Collection<Thread> getThreads() { |
022 | return this .getQueuedThreads(); |
026 | public class Task implements Runnable { |
032 | public Task(Lock lock) { |
039 | for ( int i = 0 ; i < 5 ; i++) { |
043 | System.out.printf( "%s: Get the Lock.\n" , Thread.currentThread() |
048 | TimeUnit.MILLISECONDS.sleep( 500 ); |
049 | System.out.printf( "%s: Free the Lock.\n" , Thread |
050 | .currentThread().getName()); |
051 | } catch (InterruptedException e) { |
061 | public static void main(String[] args) throws Exception { |
064 | MyLock lock = new MyLock(); |
067 | Thread threads[] = new Thread[ 5 ]; |
070 | for ( int i = 0 ; i < 5 ; i++) { |
071 | Task task = lock. new Task(lock); |
072 | threads[i] = new Thread(task); |
077 | for ( int i = 0 ; i < 15 ; 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()); |
085 | System.out.printf( "Lock: Queued Threads: %s\n" , |
086 | lock.hasQueuedThreads()); |
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" ); |
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" ); |
104 | 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 值,表明锁是否为当前线程所拥有