BoundedBuffer.java

  1. package ch.hslu.exercises.sw06.ex4;

  2. import java.util.ArrayDeque;
  3. import java.util.concurrent.Semaphore;
  4. import java.util.concurrent.TimeUnit;

  5. /**
  6.  * Puffer nach dem First In First Out Prinzip mit einer begrenzten Kapazität.
  7.  * Der Puffer ist thread sicher.
  8.  *
  9.  * @param <T> Elememente des Buffers
  10.  */
  11. public final class BoundedBuffer<T> implements Buffer<T> {

  12.     private final ArrayDeque<T> queue;
  13.     private final Semaphore putSema;
  14.     private final Semaphore takeSema;

  15.     /**
  16.      * Erzeugt einen Puffer mit bestimmter Kapazität.
  17.      *
  18.      * @param n Kapazität des Puffers
  19.      */
  20.     public BoundedBuffer(final int n) {
  21.         queue = new ArrayDeque<>(n);
  22.         putSema = new Semaphore(n);
  23.         takeSema = new Semaphore(0);
  24.     }

  25.     @Override
  26.     public void add(final T elem) throws InterruptedException {
  27.         putSema.acquire();
  28.         addSynchronized(elem);
  29.     }

  30.     @Override
  31.     public T remove() throws InterruptedException {
  32.         takeSema.acquire();
  33.         return removeSynchronized();
  34.     }

  35.     @Override
  36.     public boolean add(T elem, long millis) throws InterruptedException {
  37.         if (putSema.tryAcquire(millis, TimeUnit.MILLISECONDS)) {
  38.             addSynchronized(elem);
  39.             return true;
  40.         } else {
  41.             return false;
  42.         }
  43.     }

  44.     @Override
  45.     public T remove(long millis) throws InterruptedException {
  46.         if (takeSema.tryAcquire(millis, TimeUnit.MILLISECONDS)) {
  47.             return removeSynchronized();
  48.         } else {
  49.             return null;
  50.         }
  51.     }

  52.     public void addSynchronized(T elem) {
  53.         synchronized (queue) {
  54.             queue.addFirst(elem);
  55.         }
  56.         takeSema.release();
  57.     }

  58.     private T removeSynchronized() {
  59.         T elem;
  60.         synchronized (queue) {
  61.             elem = queue.removeLast();
  62.         }
  63.         putSema.release();
  64.         return elem;
  65.     }

  66.     @Override
  67.     public boolean empty() {
  68.         return takeSema.availablePermits() == 0;
  69.     }

  70.     @Override
  71.     public boolean full() {
  72.         return putSema.availablePermits() == 0;
  73.     }

  74.     @Override
  75.     public int size() {
  76.         return takeSema.availablePermits();
  77.     }
  78. }