使用信号量实现的有界缓冲池BoundedBuffer
来源:互联网 发布:mysql 数据库迁移 编辑:程序博客网 时间:2024/05/21 01:28
/** * author:gaoxingliang@outlook.com * created:2015年9月2日 下午8:19:08 */package datastruct;import java.util.concurrent.Semaphore;/** * 使用信号量实现的有界缓冲池 */public class BoundedBuffer<T>{ private int size; // 可用的信号量 private Semaphore avialable = null; // 是否已经有元素的信号量 private Semaphore used = null; // put的位置 take的位置 private int putPos, takePos; private T[] objs; @SuppressWarnings("unchecked") public BoundedBuffer(int size) { this.size = size; avialable = new Semaphore(size); used = new Semaphore(0); objs = (T[]) new Object[size]; putPos = takePos = 0; } public boolean isEmpty() { return used.availablePermits() == 0; } public boolean isFull() { return avialable.availablePermits() == 0; } /** * 取一个元素 * * @return * @throws InterruptedException */ public T take() throws InterruptedException { // wrong version T o = null; used.acquire(); synchronized (this) { o = objs[takePos]; objs[takePos] = null; takePos = (takePos + 1) % size; } avialable.release(); return o; } /** * 放一个元素 * * @param o * @throws InterruptedException */ public void put(T o) throws InterruptedException { avialable.acquire(); synchronized (this) { objs[putPos] = o; putPos = (putPos + 1) % size; } used.release(); }}
测试程序:
/** * * author:gaoxingliang@outlook.com * created:2015年9月2日 下午8:43:37 */package datastruct;import static org.junit.Assert.assertFalse;import static org.junit.Assert.assertTrue;import static org.junit.Assert.fail;import java.security.SecureRandom;import org.junit.Ignore;import org.junit.Test;/** * @author gxl * */public class BoundedBufferTestCase{ @Test public void testbase1() { // 测试基础方法 BoundedBuffer<Integer> bb = new BoundedBuffer<Integer>(10); assertTrue(bb.isEmpty()); assertFalse(bb.isFull()); } @Test public void testIsFullWhenPuts() throws InterruptedException { int size = 10; BoundedBuffer<Integer> bb = new BoundedBuffer<Integer>(size); assertTrue(bb.isEmpty()); assertFalse(bb.isFull()); for (int i = 0; i < size; i++) { bb.put(i); } assertTrue(bb.isFull()); assertFalse(bb.isEmpty()); } @Ignore public void testTakeWhenEmpty() { int size = 10; final BoundedBuffer<Integer> bb = new BoundedBuffer<Integer>(size); Thread taker = new Thread(new Runnable() { @Override public void run() { try { bb.take(); fail("Cannt take suc."); } catch (InterruptedException e) { } } }); try { taker.start(); Thread.sleep(10000); taker.interrupt(); taker.join(10000); assertFalse(taker.isAlive()); } catch (InterruptedException e) { fail(e.getMessage()); } } @Test public void testCorrectness() { SecureRandom r = new SecureRandom(); for (int i = 0; i< 10; i++) { boolean res = new PutTakeTest(r.nextInt(20000) + 1, r.nextInt(35) + 10, r.nextInt(50) + 10).test(); assertTrue(res); } }}
/** * * author:gaoxingliang@outlook.com * created:2015年9月2日 下午8:59:46 */package datastruct;import java.util.concurrent.CyclicBarrier;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.atomic.AtomicInteger;/** * 辅助测试BoundedBuffer安全性的测试 * * @author gxl * */public class PutTakeTest{ private int tryTime, pairCount; private final AtomicInteger putSum = new AtomicInteger(); private final AtomicInteger takeSum = new AtomicInteger(); private CyclicBarrier barrier; private static final ExecutorService es = Executors.newCachedThreadPool(); private BoundedBuffer<Integer> bb; /** * constructor * * @param tryTime * 测试次数/累加次数 * @param pairCount * 生产者和消费者各pairCount个 * @param buffSize * 缓冲池大小 */ public PutTakeTest(int tryTime, int pairCount, int buffSize) { this.tryTime = tryTime; this.pairCount = pairCount; this.barrier = new CyclicBarrier(pairCount * 2 + 1); this.bb = new BoundedBuffer<Integer>(buffSize); } public boolean test() { try { for (int i = 0; i< pairCount; i ++) { es.execute( new Producer(bb, barrier)); es.execute(new Consumer(bb, barrier)); } barrier.await();//WAIT UNTIL ALL IS READY barrier.await();//WAIT UNTIL ALL IS FINISHED return putSum.get() == takeSum.get(); } catch (Exception e) { e.printStackTrace(); return false; } } class Producer implements Runnable { private BoundedBuffer<Integer> outBuffer; private CyclicBarrier outBarrier; /** * @param bb * @param barrier */ public Producer(BoundedBuffer<Integer> bb, CyclicBarrier barrier) { super(); this.outBuffer = bb; this.outBarrier = barrier; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { try { int seed = (this.hashCode() ^ (int) System.nanoTime()); outBarrier.await(); int sum = 0; for (int i = 0; i < tryTime; i++) { outBuffer.put(seed); sum += seed; seed = xOrShift(seed); } putSum.getAndAdd(sum); outBarrier.await(); } catch (Exception e) { // TODO: handle exception } } } class Consumer implements Runnable { private BoundedBuffer<Integer> outBuffer; private CyclicBarrier outBarrier; /** * @param bb * @param barrier */ public Consumer(BoundedBuffer<Integer> bb, CyclicBarrier barrier) { super(); this.outBuffer = bb; this.outBarrier = barrier; } /* * (non-Javadoc) * * @see java.lang.Runnable#run() */ @Override public void run() { try { outBarrier.await(); int sum = 0; for (int i = 0; i < tryTime; i++) { sum += outBuffer.take(); } takeSum.getAndAdd(sum); outBarrier.await(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } } static int xOrShift(int y) { y ^= (y << 6); y ^= (y >>> 21); y ^= (y << 7); return y; }}
0 0
- 使用信号量实现的有界缓冲池BoundedBuffer
- Boundedbuffer
- 有缓冲的通道
- Thread缓冲池的实现
- 基于信号量的有界缓存
- 使用缓冲流实现文件的复制
- 有缓冲与无缓冲的区别
- 缓冲技术之二:缓冲池BufferPool的简单实现
- 使用Lock实现信号量
- 使用信号量实现同步
- 有缓冲的文件操作
- 一个简单Thread缓冲池的实现
- 信号量的例子(有顺序)
- 循环缓冲的实现
- 如何使用C#自带的GDI+双缓冲类BufferedGraphics实现双缓冲功能
- 如何使用C#自带的GDI+双缓冲类BufferedGraphics实现双缓冲功能
- 例解流缓冲的使用
- 使用 的surface缓冲
- [CV研究探讨] 计算机视觉三大顶级国际会议
- poj2955(区间dp)
- Scala 使用XML
- python实现去除文本中的中文符号和英文符号
- 开发一个安全的小网站(二)防止sql注入
- 使用信号量实现的有界缓冲池BoundedBuffer
- 编程语言入们指南
- MAC Wget安装
- Linux卡在Uncompressing Linux..... done, booting the kernel.
- linux——shell流程控制
- Java类反射再次升级
- 指针常量和常量指针的区别
- (JavaScript)案例一:二级联动
- ***HDU 1529 - Cashier Employment(差分约束)