Java并发编程中级篇(二):使用Semaphore信号量进行多个资源并发控制
2016-11-25 00:00
549 查看
上一节中我们使用了Semaphore信号量保护共享资源,但是它只能保护一个共享资源,当我们需要同时保护多个共享资源的时候,我们只需要在创建信号量的时候使用new Semaphore(int)构造方法,传入参数是你想要保护的共享资源数目。
还是PrintQueue的例子,我们把打印队列中打印机数目增加到3台,使用一个boolean[3]数组来标记打印机是否可用,同时使用3个信号量来保证这三个打印机的并发访问控制。定义一个锁来保证更改打印机状态的时候的同步控制。获取打印机资源的时候记录打印机ID,并标记打印机处于使用状态。释放打印机资源的时候,把相应ID的打印机状态置为可用。
打印Job线程类和主方法类不变
执行查看控制台日志,你可以发现每次有三个打印Job可以执行。
/** * Creates a {@code Semaphore} with the given number of * permits and nonfair fairness setting. * * @param permits the initial number of permits available. * This value may be negative, in which case releases * must occur before any acquires will be granted. */ public Semaphore(int permits) { sync = new NonfairSync(permits); }
还是PrintQueue的例子,我们把打印队列中打印机数目增加到3台,使用一个boolean[3]数组来标记打印机是否可用,同时使用3个信号量来保证这三个打印机的并发访问控制。定义一个锁来保证更改打印机状态的时候的同步控制。获取打印机资源的时候记录打印机ID,并标记打印机处于使用状态。释放打印机资源的时候,把相应ID的打印机状态置为可用。
public class PrintQueue { private boolean freePrinters[]; private Lock lockPrinters; private Semaphore semaphore; public PrintQueue() { this.freePrinters = new boolean[3]; this.lockPrinters = new ReentrantLock(); this.semaphore = new Semaphore(3); for (int i = 0; i < 3; i++) { this.freePrinters[i] = true; } } public void printJob(Object object) { try { semaphore.acquire(); int assignedPrinter = getPrinter(); long duration = (long)(Math.random() * 10); System.out.printf("%s: Print a Job in printer %d duration %d seconds.\n", Thread.currentThread().getName(), assignedPrinter, duration); TimeUnit.SECONDS.sleep(duration); freePrinter(assignedPrinter); } catch (InterruptedException e) { e.printStackTrace(); } finally { semaphore.release(); } } private int getPrinter() { lockPrinters.lock(); int printNo = -1; try { for (int i = 0; i < freePrinters.length; i++) { if (freePrinters[i]) { printNo = i; freePrinters[i] = false; break; } } } finally { lockPrinters.unlock(); } return printNo; } private void freePrinter(int printNo) { lockPrinters.lock(); try { freePrinters[printNo] = true; } finally { lockPrinters.unlock(); } }
打印Job线程类和主方法类不变
public class Job implements Runnable{ private PrintQueue printQueue; public Job(PrintQueue printQueue) { this.printQueue = printQueue; } @Override public void run() { System.out.printf("%s: Going to print a Job.\n", Thread.currentThread().getName()); printQueue.printJob(new Object()); System.out.printf("%s: The Job has been printed.\n", Thread.currentThread().getName()); } }
public class Main { public static void main(String[] args) { PrintQueue printQueue = new PrintQueue(); Thread[] threads = new Thread[10]; for (int i = 1; i < 10; i++) { threads[i] = new Thread(new Job(printQueue)); } for (int i = 1; i < 10; i++) { threads[i].start(); } } }
执行查看控制台日志,你可以发现每次有三个打印Job可以执行。
Thread-0: Going to print a Job. Thread-8: Going to print a Job. Thread-7: Going to print a Job. Thread-6: Going to print a Job. Thread-5: Going to print a Job. Thread-4: Going to print a Job. Thread-3: Going to print a Job. Thread-2: Going to print a Job. Thread-1: Going to print a Job. Thread-8: Print a Job in printer 1 duration 2 seconds. Thread-7: Print a Job in printer 2 duration 6 seconds. Thread-0: Print a Job in printer 0 duration 2 seconds. Thread-0: The Job has been printed. Thread-5: Print a Job in printer 1 duration 7 seconds. Thread-6: Print a Job in printer 0 duration 9 seconds. Thread-8: The Job has been printed. Thread-7: The Job has been printed. Thread-4: Print a Job in printer 2 duration 1 seconds. Thread-4: The Job has been printed. Thread-3: Print a Job in printer 2 duration 6 seconds. Thread-5: The Job has been printed. Thread-2: Print a Job in printer 1 duration 7 seconds. Thread-6: The Job has been printed. Thread-1: Print a Job in printer 0 duration 2 seconds. Thread-3: The Job has been printed. Thread-1: The Job has been printed. Thread-2: The Job has been printed.
相关文章推荐
- Java并发编程中级篇(一):使用Semaphore信号量进行并发控制
- java多线程-Semaphore信号量使用 介绍 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源
- iOS GCD中级篇 - dispatch_semaphore(信号量)的理解及使用
- 使用信号量 进行windows线程同步 (Semaphore)
- 网络编程(40)—— 使用信号量semaphore进行多进程间的同步
- java并发编程系列之Semaphore信号量的使用
- Java: 使用信号量(Semaphore)保护多个共享资源的访问
- 网络编程(39)—— 使用信号量semaphore进行多线程同步
- Android使用信号量Semaphore进行多线程任务调度
- Java并发编程: 使用Semaphore限制资源并发访问的线程数
- Android使用信号量Semaphore进行多线程任务调度
- iOS GCD中级篇 - dispatch_semaphore(信号量)的理解及使用
- iOS GCD中级篇 - dispatch_semaphore(信号量)的理解及使用
- 互联网进行限流策略的Semaphore信号量使用
- 在Eclipse中使用JUnit4进行单元测试(中级篇)
- [jQuery]使用jQuery.Validate进行客户端验证(中级篇-下)——不使用微软验证控件的理由
- C#多线程编程之:使用Semaphore类限制资源并发访问数
- [jQuery]使用jQuery.Validate进行客户端验证(中级篇-上)——不使用微软验证控件的理由
- 在Eclipse中使用JUnit4进行单元测试(中级篇)
- 使用LoadRunner进行资源占用率进行分析