本文主要是介绍设计模式 Concurrency 之 Semaphore 信号量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
- 定义
- 适用场景
- 例子
1.定义
Semaphore是一种基于计数的信号量。它可以设定一个阈值,基于此,多个线程竞争获取许可信号,做完自己的申请后归还,超过阈值后,线程申请许可信号将会被阻塞。Semaphore可以用来构建一些对象池,资源池之类的,比如数据库连接池,我们也可以创建计数为1的Semaphore,将其作为一种类似互斥锁的机制,这也叫二元信号量,表示两种互斥状态
2. 适用场景
- 保护一个重要[代码]部分 防止一次超过N个线程进入
- 在两个线程之间发送信号
3. 例子
Lock
package com.hqq.concurrency.semaphone;/*** Lock* Created by heqianqian on 2017/7/30.*/
public interface Lock {void release() throws InterruptedException;void acquire() throws InterruptedException;}
Semaphore
package com.hqq.concurrency.semaphone;/*** Semaphore* Created by heqianqian on 2017/7/30.*/
public class Semaphore implements Lock {private final int licenses;private int counter;public Semaphore(int counter) {this.counter = counter;this.licenses = counter;}public int getNumLicenses() {return this.licenses;}public int getAvailableLicenses() {return counter;}@Overridepublic synchronized void acquire() throws InterruptedException {while (counter == 0) {wait();}counter = counter - 1;}@Overridepublic synchronized void release(){if (counter < licenses) {counter = counter + 1;notify();}}
}
FruitType:
package com.hqq.concurrency.semaphone;/*** FruitType* 水果类型* Created by heqianqian on 2017/7/30.*/
public enum FruitType {APPLE, ORANGE, BANANA;}
Fruit
package com.hqq.concurrency.semaphone;/*** Fruit* <p>* Created by heqianqian on 2017/7/30.*/
public class Fruit {private FruitType fruitType;public Fruit(FruitType fruitType) {this.fruitType = fruitType;}public FruitType getFruitType() {return fruitType;}@Overridepublic String toString() {switch (fruitType) {case ORANGE:return "Orange";case APPLE:return "Apple";case BANANA:return "Banana";default:return "";}}
}
FruitBowl
package com.hqq.concurrency.semaphone;import java.util.ArrayList;
import java.util.List;/*** FruitBowl* Created by heqianqian on 2017/7/30.*/
public class FruitBowl {private List<Fruit> fruitList = new ArrayList<>();public int countFruit() {return fruitList.size();}public void put(Fruit fruit) {fruitList.add(fruit);}public Fruit get() {if (fruitList.size() == 0) {return null;}return fruitList.remove(0);}
}
FruitShop
package com.hqq.concurrency.semaphone;/*** FruitShop* Created by heqianqian on 2017/7/30.*/
public class FruitShop {private FruitBowl[] fruitBowls = {new FruitBowl(),new FruitBowl(),new FruitBowl()};private boolean[] available = {true,true,true};private Semaphore semaphore;public FruitShop() {for (int i = 0; i < 100; i++) {fruitBowls[0].put(new Fruit(FruitType.APPLE));fruitBowls[0].put(new Fruit(FruitType.BANANA));fruitBowls[0].put(new Fruit(FruitType.ORANGE));}semaphore = new Semaphore(3);}public synchronized int countFruit() {return fruitBowls[0].countFruit() + fruitBowls[1].countFruit()+ fruitBowls[2].countFruit();}public synchronized FruitBowl takeBowl() {FruitBowl fruitBowl = null;try {semaphore.acquire();if (available[0]) {fruitBowl = fruitBowls[0];available[0] = false;} else if (available[1]) {fruitBowl = fruitBowls[1];available[1] = false;} else if (available[2]) {fruitBowl = fruitBowls[2];available[2] = false;}} catch (InterruptedException e) {e.printStackTrace();} finally {semaphore.release();}return fruitBowl;}public synchronized void returnBowl(FruitBowl fruitBowl) {if (fruitBowl == fruitBowls[0]) {available[0] = true;} else if (fruitBowl == fruitBowls[1]) {available[1] = true;} else if (fruitBowl == fruitBowls[2]) {available[2] = true;}}}
Customer
package com.hqq.concurrency.semaphone;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;/*** Customer* Created by heqianqian on 2017/7/30.*/
public class Customer extends Thread {private static final Logger LOGGER = LoggerFactory.getLogger(Customer.class);private String name;private FruitShop fruitShop;private FruitBowl fruitBowl;public Customer(String name, FruitShop fruitShop) {this.name = name;this.fruitShop = fruitShop;this.fruitBowl = new FruitBowl();}@Overridepublic void run() {while (fruitShop.countFruit() > 0) {FruitBowl bowl = fruitShop.takeBowl();Fruit fruit;if (bowl != null && (fruit = bowl.get()) != null) {LOGGER.info("{} took an {}", name, fruit);fruitBowl.put(fruit);fruitShop.returnBowl(bowl);}}LOGGER.info("{} took {}", name, fruitBowl);}
}
App
package com.hqq.concurrency.semaphone;/*** App* Created by heqianqian on 2017/7/30.*/
public class App {/*** main method** @param args*/public static void main(String[] args) {FruitShop shop = new FruitShop();new Customer("Peter", shop).start();new Customer("Paul", shop).start();new Customer("Mary", shop).start();new Customer("John", shop).start();new Customer("Ringo", shop).start();new Customer("George", shop).start();}
}
输出结果:
INFO [2017-08-09 01:51:34,148] com.hqq.concurrency.semaphone.Customer: Paul took an Apple
INFO [2017-08-09 01:51:34,148] com.hqq.concurrency.semaphone.Customer: Paul took an Banana
INFO [2017-08-09 01:51:34,148] com.hqq.concurrency.semaphone.Customer: Mary took an Orange
INFO [2017-08-09 01:51:34,148] com.hqq.concurrency.semaphone.Customer: Paul took an Apple
INFO [2017-08-09 01:51:34,164] com.hqq.concurrency.semaphone.Customer: Mary took an Banana
INFO [2017-08-09 01:51:34,164] com.hqq.concurrency.semaphone.Customer: Paul took an Orange
INFO [2017-08-09 01:51:34,164] com.hqq.concurrency.semaphone.Customer: Mary took an Apple
INFO [2017-08-09 01:51:34,164] com.hqq.concurrency.semaphone.Customer: Paul took an Banana
INFO [2017-08-09 01:51:34,164] com.hqq.concurrency.semaphone.Customer: Mary took an Orange
INFO [2017-08-09 01:51:34,164] com.hqq.concurrency.semaphone.Customer: Paul took an Apple
INFO [2017-08-09 01:51:34,164] com.hqq.concurrency.semaphone.Customer: Mary took an Banana
...
这篇关于设计模式 Concurrency 之 Semaphore 信号量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!