View Javadoc
1   package ch.hslu.exercises.sw06.ex4;
2   
3   import java.util.ArrayDeque;
4   import java.util.concurrent.Semaphore;
5   import java.util.concurrent.TimeUnit;
6   
7   /**
8    * Puffer nach dem First In First Out Prinzip mit einer begrenzten Kapazität.
9    * Der Puffer ist thread sicher.
10   *
11   * @param <T> Elememente des Buffers
12   */
13  public final class BoundedBuffer<T> implements Buffer<T> {
14  
15      private final ArrayDeque<T> queue;
16      private final Semaphore putSema;
17      private final Semaphore takeSema;
18  
19      /**
20       * Erzeugt einen Puffer mit bestimmter Kapazität.
21       *
22       * @param n Kapazität des Puffers
23       */
24      public BoundedBuffer(final int n) {
25          queue = new ArrayDeque<>(n);
26          putSema = new Semaphore(n);
27          takeSema = new Semaphore(0);
28      }
29  
30      @Override
31      public void add(final T elem) throws InterruptedException {
32          putSema.acquire();
33          addSynchronized(elem);
34      }
35  
36      @Override
37      public T remove() throws InterruptedException {
38          takeSema.acquire();
39          return removeSynchronized();
40      }
41  
42      @Override
43      public boolean add(T elem, long millis) throws InterruptedException {
44          if (putSema.tryAcquire(millis, TimeUnit.MILLISECONDS)) {
45              addSynchronized(elem);
46              return true;
47          } else {
48              return false;
49          }
50      }
51  
52      @Override
53      public T remove(long millis) throws InterruptedException {
54          if (takeSema.tryAcquire(millis, TimeUnit.MILLISECONDS)) {
55              return removeSynchronized();
56          } else {
57              return null;
58          }
59      }
60  
61      public void addSynchronized(T elem) {
62          synchronized (queue) {
63              queue.addFirst(elem);
64          }
65          takeSema.release();
66      }
67  
68      private T removeSynchronized() {
69          T elem;
70          synchronized (queue) {
71              elem = queue.removeLast();
72          }
73          putSema.release();
74          return elem;
75      }
76  
77      @Override
78      public boolean empty() {
79          return takeSema.availablePermits() == 0;
80      }
81  
82      @Override
83      public boolean full() {
84          return putSema.availablePermits() == 0;
85      }
86  
87      @Override
88      public int size() {
89          return takeSema.availablePermits();
90      }
91  }