线程同步工具类之信号量(Semaphore)
2015-11-13 00:00
232 查看
计数信号量用来控制同时访问某个资源的操作数量。还可以用来实现某种资源池,例如消费者和生产者之间的控制,例如生产者向容器中添加元素,消费者删除元素,容器是有边界的。
Semaphore总管理着一组虚拟的许可,许可的数量可以在构建初始化信号量的时候设定
数量可以是容器的边界或者是线程池的线程数量。在如容器内添加元素时,要先获取Semaphore的一个许可 sem.acquire(),如果容器的元素已经满了,sem.acquire()会阻塞,当容器中删除了一个元素,就释放一个许可。
下面可以实现一个带边界的容器BoundedHashSet
测试类,定义一个要向容器边界为3的容器添加的数组元素,一个线程添加元素,一个线程删除元素
可以看下运行结果,在线程添加第四个元素时,要等其它线程删除元素,所以阻塞了1998毫秒的时间
Semaphore总管理着一组虚拟的许可,许可的数量可以在构建初始化信号量的时候设定
Semaphore sem= new Semaphore(3);
数量可以是容器的边界或者是线程池的线程数量。在如容器内添加元素时,要先获取Semaphore的一个许可 sem.acquire(),如果容器的元素已经满了,sem.acquire()会阻塞,当容器中删除了一个元素,就释放一个许可。
下面可以实现一个带边界的容器BoundedHashSet
public class BoundedHashSet<T> { private final Set<T> set; private final Semaphore sem; public BoundedHashSet(int bound){ this.set=Collections.synchronizedSet(new HashSet<T>()); sem=new Semaphore(bound); } public boolean add(T o) throws InterruptedException{ long start=System.currentTimeMillis(); System.out.println("开始添加元素"); sem.acquire(); boolean wasAdded=false; try { wasAdded=set.add(o); System.out.println("添加成功"); for (Iterator i=set.iterator();i.hasNext();) { String string=(String)i.next(); System.out.println(string); } System.out.println(System.currentTimeMillis()-start); return wasAdded; } finally{ if(!wasAdded){ sem.release(); System.out.println("添加失败"); } } } public boolean remove(Object o){ boolean wasRemoved=set.remove(o); if(wasRemoved){ sem.release(); System.out.println("释放元素:"+o); } return wasRemoved; } }
测试类,定义一个要向容器边界为3的容器添加的数组元素,一个线程添加元素,一个线程删除元素
public class sem { public static void main(String[] args) { final BoundedHashSet<String> boundedHashSet=new BoundedHashSet<>(3); final String[] timStrings={"a","b","c","d","e","f"}; Thread addThread=new Thread(new Runnable() { @Override public void run() { // TODO Auto-generated method stub try { int count=1; for (String string : timStrings) { Thread.sleep(1000); if(boundedHashSet.add(string)){ System.out.println("添加成功第"+count+"个"+string); } count++; } } catch (InterruptedException e) { e.printStackTrace(); } } }); addThread.start(); Thread releaseThread=new Thread(new Runnable() { @Override public void run() { int count=1; try { for (String string : timStrings) { if(count==1){ Thread.sleep(6000); }else{ Thread.sleep(1500); } boundedHashSet.remove(string); System.out.println("删除第"+count+"元素"); count++; } Thread.sleep(1500); } catch (InterruptedException e) { e.printStackTrace(); } } }); releaseThread.start(); } }
可以看下运行结果,在线程添加第四个元素时,要等其它线程删除元素,所以阻塞了1998毫秒的时间
相关文章推荐
- C#通过Semaphore类控制线程队列的方法
- linux多线程编程详解教程(线程通过信号量实现通信代码)
- C#使用semaphore来管理异步下载请求的方法
- Python多线程同步Lock、RLock、Semaphore、Event实例
- JAVA 多线程之信号量(Semaphore)实例详解
- Python多进程同步Lock、Semaphore、Event实例
- Linux设备驱动并发控制详解(自旋锁,信号量)
- 信号量
- 信号量、互斥锁,读写锁和条件变量的区别
- java并发包里的semaphore的用法
- 多线程编程(2):线程的同步
- Threading in C#, phase 2
- RCU - Basics
- 生产者消费者模拟
- 互斥锁与条件变量的配合!
- 信号量 互斥锁 条件变量的区别
- asp.net中需要创建唯一的序号
- win32多线程程序设计
- Delphi中最常用的三种线程同步技术
- linux网络编程----->线程同步-->信号量