监控信号量类

Java 9并发编程指南 目录

信号量是一个计数器,保护对一个或多个共享资源的访问。

1965年Edsgar Dijkstra引入信号量概念,并在THEOS操作系统中第一次使用。

当线程想要使用共享资源时,它必须获得一个信号量。如果信号量的内部计数器大于0,信号量递减计数器值并允许访问共享资源。如果信号量计数器等于0,则阻塞线程,直到计数器大于0。当线程使用完共享资源时,则必须释放信号量,递增信号量的内部计数器值。

信号量在Java的Semaphore类中实现。

本节将学习关于信号量的状态信息,以及如何获取这些信息。

准备工作

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

实现过程

通过如下步骤实现范例:

  1. 创建名为Task的类,实现Runnable接口:

    public class Task implements Runnable {
    
  2. 声明名为semaphore的私有Semaphore属性:

    	private final Semaphore semaphore;
    
  3. 实现类构造函数,初始化属性:

    	public Task(Semaphore semaphore){
    		this.semaphore=semaphore;
    	}
    
  4. 实现run()方法,首先获取信号量属性的许可并输出指明这种情况的信息到控制台:

    	@Override
    	public void run() {
    		try {
    			semaphore.acquire();
    			System.out.printf("%s: Get the semaphore.\n", Thread.currentThread().getName());
    
  5. 然后使用sleep()方法设置线程休眠两秒钟,最后释放许可并输出指明这种情况的信息到控制台:

    			TimeUnit.SECONDS.sleep(2);
    			System.out.println(Thread.currentThread().getName()+": Release the semaphore.");
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		} finally {
    			semaphore.release();
    		}
    	}
    }
    
  6. 实现本范例主类,创建名为Main的类,包含main()方法:

    public class Main {
    	public static void main(String[] args) throws Exception{
    
  7. 创建名为semaphore的Semaphore对象,包含三个许可:

    		Semaphore semaphore=new Semaphore(3);
    
  8. 创建数组存储10个Thread对象:

    		Thread threads[]=new Thread[10];
    
  9. 创建和启动10个Thread对象执行10个Task对象。启动线程之后,设置线程休眠200毫秒,调用showLog()方法输出Semaphore类的信息到控制台:

    		for (int i=0; i<threads.length; i++) {
    			Task task=new Task(semaphore);
    			threads[i]=new Thread(task);
    			threads[i].start();
    			TimeUnit.MILLISECONDS.sleep(200);
    			showLog(semaphore);
    		}
    
  10. 创建重复五次操作的循环,每次操作调用showLog()方法输出semaphore的信息到控制台,并设置线程休眠1秒钟:

    		for (int i=0; i<5; i++) {
    			showLog(semaphore);
    			TimeUnit.SECONDS.sleep(1);
    		}
    	}
    
  11. 实现showLog()方法,将Semaphore对象作为参数接收。输出关于semaphore的可用许可、排队线程和许可的信息到控制台:

    	private static void showLog(Semaphore semaphore) {
    		System.out.printf("********************\n");
    		System.out.printf("Main: Semaphore Log\n");
    		System.out.printf("Main: Semaphore: Avalaible Permits: %d\n", semaphore.availablePermits());
    		System.out.printf("Main: Semaphore: Queued Threads: %s\n", semaphore.hasQueuedThreads());
    		System.out.printf("Main: Semaphore: Queue Length: %d\n", semaphore.getQueueLength());
    		System.out.printf("Main: Semaphore: Fairness: %s\n", semaphore.isFair());
    		System.out.printf("********************\n"); 
    	}
    }
    

扩展学习

本节使用到如下方法获得semaphore的信息:

  • availablePermits():返回int值,是信号量可用资源的数量。
  • hasQueuedThreads():返回Boolean值,指明是否有线程等待由信号量保护的资源。
  • getQueueLength():返回等待由信号量保护的资源的线程数。
  • isFair():返回Boolean值,指明信号量是否激活了公平模式。当公平模式已激活(返回true值),锁需要选择其它线程并允许访问共享资源,它选择最长等待线程。如果公平模式未激活(返回false值),则无法保证选择哪个线程来获得对共享资源的访问。

更多关注

  • 第三章“线程同步功能”中的“控制并发访问资源副本”小节
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值