Podobny problem jak tu:
https://stackoverflow.com/questions/5237283/java-blocking-queue-containing-only-unique-elements
Potrzebuję tylko metody put
i take
.
Naklepałem tak o:
public class ConcurrencyBufferSetTest {
@Test
public void testDuplicates() throws InterruptedException {
// given:
int x = 10;
int y = 20;
// when:
ConcurrencyBuffer<Integer> buffer = new ConcurrencyBufferSet<>();
buffer.put(x);
buffer.put(y);
buffer.put(x);
int sizeBeforeTake = buffer.size();
int elem1 = buffer.take();
int sizeAfterTake1 = buffer.size();
int elem2 = buffer.take();
int sizeAfterTake2 = buffer.size();
// then:
assertEquals(2, sizeBeforeTake);
assertEquals(1, sizeAfterTake1);
assertEquals(0, sizeAfterTake2);
assertEquals(10, elem1);
assertEquals(20, elem2);
}
@Test
public void testEmpty() throws InterruptedException {
ConcurrencyBuffer<Integer> buffer = new ConcurrencyBufferSet<>();
Thread consumer = new Thread(() -> {
try {
int x = buffer.take();
assertNotNull(x);
} catch (InterruptedException e) {
fail();
}
});
Thread producer = new Thread(() -> {
try {
TimeUnit.MILLISECONDS.sleep(100);
buffer.put(1);
} catch (InterruptedException e) {
fail();
}
});
consumer.start();
producer.start();
consumer.join();
producer.join();
}
}
public class ConcurrencyBufferSet<T> implements ConcurrencyBuffer<T> {
private Set<T> set = new LinkedHashSet<>();
@Override
public void put(T t) throws InterruptedException {
synchronized (this) {
set.add(t);
notify();
}
}
@Override
public T take () throws InterruptedException {
synchronized (this) {
while (set.isEmpty()) {
wait();
}
Iterator<T> it = set.iterator();
T t = it.next();
it.remove();
notify();
return t;
}
}
@Override
public int size() {
return set.size();
}
@Override public Set<T> getBufferSnapshot () {
return new LinkedHashSet<>(set);
}
}
- Jak na proste rozwiązanie czy może być?
- Jak to porządnie przetestować?
- Jak w drugim teście zrobić by consumer leciał przed producerem? Wojciech Seliga zabronił używać locków.