监控Lock接口

Java 9并发编程指南 目录

Lock接口是Java并发API提供的基本机制之一,用来同步代码块。此接口定义了临界区,即访问共享资源的代码块,不能同时执行多个线程。这种机制通过Lock接口和ReentrantLock类实现。

本节讲学习关于Lock对象的信息以及如何获取这些信息。

准备工作

本范例通过Eclipse开发工具实现。如果使用诸如NetBeans的开发工具,打开并创建一个新的Java项目。

实现过程

通过如下步骤实现范例:

  1. 创建名为MyLock的类,继承ReentrantLock类:

    public class MyLock extends ReentrantLock {
    
  2. 实现getOwnerName()方法,此方法返回具有锁(如果有)控制的线程名称,使用名为getOwner()的Lock类保护方法:

    	public String getOwnerName() {
    		if (this.getOwner()==null) {
    			return "None";
    		}
    		return this.getOwner().getName();
    	}
    
  3. 实现getThreads()方法,此方法返回锁中排队的线程列表,使用名为getQueuedThreads()的Lock类保护方法:

    	public Collection<Thread> getThreads() {
    		return this.getQueuedThreads();
    	}
    }
    
  4. 创建名为Task的类,实现Runnable接口:

    public class Task implements Runnable{
    
  5. 声明名为lock的私有Lock属性:

    	private final Lock lock;
    
  6. 实现类构造函数,初始化属性:

    	public Task (Lock lock) {
    		this.lock=lock;
    	}
    
  7. 实现run()方法,创建重复五次的循环:

    	@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 class Main {
    	public static void main(String[] args) throws Exception {
    
  11. 创建名为lock的MyLock对象:

    		MyLock lock=new MyLock();
    
  12. 创建包含五个thread对象的数组:

    		Thread threads[]=new Thread[5];
    
  13. 创建并启动五个线程,执行五个Task对象:

    		for (int i=0; i<5; i++) {
    			Task task=new Task(lock);
    			threads[i]=new Thread(task);
    			threads[i].start();
    		}
    
  14. 创建重复15次的循环:

    		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. 显示排队等待锁定的线程的数量和名称:

    			System.out.printf("Lock: Queued Threads: %s\n", lock.hasQueuedThreads());
    			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);
    		}
    	}
    }
    

工作原理

本节实现了继承ReentrantLock类的MyLock类,返回不可用的信息,否则是ReentrantLock类的受保护数据。通过MyLock类实现了如下方法:

  • getOwnerName():只有一个线程能够执行受Lock对象保护的临界区。这个锁存储正在执行临界区的线程,此线程通过ReentrantLock类的getOwner()方法返回。
  • getThreads():当一个线程执行临界区时,其它线程在继续执行临界区之前试图设置此线程休眠。ReentrantLock类的getQueuedThreads()保护方法返回等待执行临界区的线程列表。

我们还使用了ReentrantLock类实现的其它方法:

  • hasQueuedThreads():此方法返回Boolean值,指明是否有线程等待获取调用ReentrantLock
  • getQueueLength():此方法返回等待获取调用ReentrantLock的线程数量
  • isLocked():此方法返回Boolean值,指明调用ReentrantLock是否属于一个线程
  • isFair():此方法返回Boolean值,指明调用ReentrantLock是否激活公平模式

扩展学习

ReentrantLock类中还有其它方法用来获取Lock对象的信息:

  • getHoldCount():返回当前线程获得锁的次数
  • isHeldByCurrentThread():返回Boolean值,指明当前线程是否拥有锁

更多关注

  • 第二章“基础线程同步”中的“锁同步代码块”小节
  • 第八章“定制并发类”中的“实现自定义Lock类”小节

猜你喜欢

转载自blog.csdn.net/nicolastsuei/article/details/84646009