Synchronization doesnt quite work - java

I have the following code which I'm trying to write a LRU Cache. I have a runner class that I'm running against random capacity of the cache. However, Cache size is exceeding it is capacity. When I make the FixLRU method synchronized, it becomes more accurate when the cache size is more than 100 however it gets slower. When I remove the synchronized keyword, cache is becoming less accurate.
Any ideas how to make this work properly? more accurate?
import java.util.concurrent.ConcurrentHashMap;
public abstract class Cache<TKey, TValue> implements ICache<TKey,TValue>{
private final ConcurrentHashMap<TKey,TValue> _cache;
protected Cache()
{
_cache= new ConcurrentHashMap<TKey, TValue>();
}
protected Cache(int capacity){
_cache = new ConcurrentHashMap<TKey, TValue>(capacity);
}
#Override
public void Put(TKey key, TValue value) {
_cache.put(key, value);
}
#Override
public TValue Get(TKey key) {
TValue value = _cache.get(key);
return value;
}
#Override
public void Delete(TKey key) {
_cache.remove(key);
}
#Override
public void Purge() {
for(TKey key : _cache.keySet()){
_cache.remove(key);
}
}
public void IterateCache(){
for(TKey key: _cache.keySet()){
System.out.println("key:"+key+" , value:"+_cache.get(key));
}
}
public int Count()
{
return _cache.size();
}
}
import java.util.concurrent.ConcurrentLinkedQueue;
public class LRUCache<TKey,TValue> extends Cache<TKey,TValue> implements ICache<TKey, TValue> {
private ConcurrentLinkedQueue<TKey> _queue;
private int capacity;
public LRUCache(){
_queue = new ConcurrentLinkedQueue<TKey>();
}
public LRUCache(int capacity){
this();
this.capacity = capacity;
}
public void Put(TKey key, TValue value)
{
FixLRU(key);
super.Put(key, value);
}
private void FixLRU(TKey key)
{
if(_queue.contains(key))
{
_queue.remove(key);
super.Delete(key);
}
_queue.offer(key);
while(_queue.size() > capacity){
TKey keytoRemove =_queue.poll();
super.Delete(keytoRemove);
}
}
public TValue Get(TKey key){
TValue _value = super.Get(key);
if(_value == null){
return null;
}
FixLRU(key);
return _value;
}
public void Delete(TKey key){
super.Delete(key);
}
}
public class RunningLRU extends Thread{
static LRUCache<String, String> cache = new LRUCache<String, String>(50);
public static void main(String [ ] args) throws InterruptedException{
Thread t1 = new RunningLRU();
t1.start();
Thread t2 = new RunningLRU();
t2.start();
Thread t3 = new RunningLRU();
t3.start();
Thread t4 = new RunningLRU();
t4.start();
try {
t1.join();
t2.join();
t3.join();
t4.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(cache.toString());
cache.IterateCache();
System.out.println(cache.Count());
}
#Override
public void run() {
for(int i=0;i<100000;i++)
cache.Put("test"+i, "test"+i);
}
}

I would clean up additional entries after adding your entry. This minimises the time that the cache will be larger than you wanted. You can also trigger size() to perform a cleanup.
Any ideas how to make this work properly?
Does your test reflect how your application behaves? It may be that the cache behaves properly (or much closer to it) when you have not hammering it. ;)
If this test does reflect your application behaviour then perhaps an LRUCache is not the best choice.

Your problem seems to be that you aren't using the special synchronized version of the put method putIfAbsent(). If you don't use it, a ConcurrentHashMap behaves as if not synchronized - like a normal Map eg HashMap.
When you use it, you must continue to use only the returned value, so your Put() method doesn't have the correct signature (it should return TValue) to support concurrency. You'll need to redesign your interface.
Also, in java land, unlike .Net land, we name our methods with a leading lowercase, eg put(), not Put(). It would behove you to rename your methods thus.

Related

Synchronize by value rather that object

I implemented a simple locking solution that creates a lock for a value rather than object and want to know the experts' opinion for possible performance or security drawbacks.
The idea is to use it for account balance update acquiring the lock for unique account number.
Here is an implementation:
import java.util.*;
public class Mutex<T> {
private final Set<T> set = new HashSet();
public synchronized Lock acquireLock(
T value
) throws InterruptedException {
while(!set.add(value)) {
this.wait();
}
return new Lock(value);
}
public class Lock {
private final T value;
public Lock(T value) {
this.value = value;
}
public T getValue() {
return value;
}
public void release() {
synchronized(Mutex.this) {
set.remove(value);
Mutex.this.notifyAll();
}
}
}
}
And here is a sample usage to check the operability:
public class Test {
private Mutex mutex = new Mutex();
public static void main(String[] args) {
Test test = new Test();
Thread t1 = new Thread(() -> {
try {
test.test("SameValue");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
t1.setName("Thread 1");
Thread t2 = new Thread(() -> {
try {
test.test("SameValue");
} catch (InterruptedException ex) {
ex.printStackTrace();
}
});
t2.setName("Thread 2");
t1.start();
t2.start();
}
public void test(String value)
throws
InterruptedException {
Lock lock = mutex.acquireLock(value);
try {
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName());
} finally {
lock.release();
}
}
}
Regarding your implementation,
I would have use a Set instead of a List to hold your values (I assume the values have proper equals/hashcode for this to make sense): the List#contains method is in O(n) which might be expensive if you have a lot of IBAN used at the same time.
Also, you should avoid using synchronize(this) (which is the same as the synchronized keyword on method).
To solve your problem, I use something like this:
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Locks<T> {
private final Lock lock = new ReentrantLock();
//a Bimap from guava might be better here if you have the dependency
//in your project
private final Map<Reference<?>, T> valuePerReference = new HashMap<>();
private final Map<T, Reference<Lock>> locks = new HashMap<>();
private final ReferenceQueue<Lock> lockReferenceQueue = new ReferenceQueue<>();
public Locks() {
final Thread cleanerThread = new Thread(new Cleaner());
cleanerThread.setDaemon(true);
cleanerThread.start();
}
/**
* #param value the value the synchronization must be made on
* #return a lock that can be used to synchronize block of code.
*/
public Lock getLock(T value) {
lock.lock();
try {
return getExistingLock(value).orElseGet(() -> createNewLock(value));
} finally {
lock.unlock();
}
}
private Optional<Lock> getExistingLock(T value) {
return Optional.ofNullable(locks.get(value)).map(Reference::get);
}
private Lock createNewLock(T value) {
//I create ReentrantLock here but a Supplier<Lock> could be a parameter of this
//class to make it more generic. Same remark for SoftReference below.
final Lock lock = new ReentrantLock();
final Reference<Lock> reference = new SoftReference<>(lock, lockReferenceQueue);
this.locks.put(value,reference);
this.valuePerReference.put(reference,value);
return lock;
}
private void removeLock(Reference<?> reference) {
lock.lock();
try {
final T value = valuePerReference.remove(reference);
locks.remove(value);
} finally {
lock.unlock();
}
}
private class Cleaner implements Runnable {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
final Reference<? extends Lock> garbaged = lockReferenceQueue.remove();
removeLock(garbaged);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
}
I then use this like this:
import java.util.concurrent.locks.Lock;
public class Usage {
private final Locks<String> locks = new Locks<>();
public void doSomethind(String iban) {
final Lock lock = locks.getLock(iban);
lock.lock();
try {
//.. do something with your iban
} finally {
lock.unlock();
}
}
}
Although it uses ReentrantLock, the code can be easily modified for ReadWriteLock for instance.

Thread-safe locking/sychronizing to one permit per resource with multiple resources

I need to implement thread-safe synchronization to multiple resources, where each resource can be accessed by one thread at a time, but different resources can be accessed concurrently. I have come up with the following code, meant to be used in a try-with-resources statement.
public class Gatekeeper implements AutoCloseable
{
private static final ConcurrentMap<Long, ReentrantLock> lockMap = new ConcurrentHashMap<>();
private final ReentrantLock lock;
private final Long key;
public Gatekeeper(Long key)
{
this.key = key;
lock = lockMap.computeIfAbsent(key, (Long absentKey) -> new ReentrantLock(true)); // computeIfAbsent is an atomic operation
try
{
lock.tryLock(30, TimeUnit.SECONDS);
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
throw new Something(":(", e);
}
}
#Override
public void close()
{
if(lock.isHeldByCurrentThread())
{
lock.unlock();
}
}
}
One problem with this code is that no items are ever removed from the lockMap, and I don't know how to do this thread-safe. The following is definitely not thread-safe:
#Override
public void close()
{
if (lock.isHeldByCurrentThread())
{
if (lock.getQueueLength() == 1) // todo: getQueueLength is meant for system monitoring purposes only
{
lockMap.remove(key); // todo: not thread-safe, queuelength could have changed by now
}
lock.unlock();
}
}
the documentation for getQueueLength:
Returns an estimate of the number of threads waiting to
acquire this lock. The value is only an estimate because the number of
threads may change dynamically while this method traverses
internal data structures. This method is designed for use in
monitoring of the system state, not for synchronization
control.
Does anyone know a solution for this? Are there different strategies to achieve my goal?
After some more experimentation I came up with the code below, can anyone comment on whether this is a good approach and the code is correct?
public class Gatekeeper implements AutoCloseable
{
private static final ConcurrentMap<Long, ReentrantLock> lockMap = new ConcurrentHashMap<>();
private final ReentrantLock lock;
private final Long key;
private static final ConcurrentMap<Long, Integer> claimsPerLock = new ConcurrentHashMap<>();
private static final Object mutex = new Object();
public Gatekeeper(Long key)
{
this.key = key;
synchronized (mutex)
{
lock = lockMap.computeIfAbsent(key, (Long absentKey) -> new ReentrantLock(true));
claimsPerLock.compute(key, (k, oldValue) -> oldValue == null ? 1 : ++oldValue);
}
try
{
if(!lock.tryLock(30, TimeUnit.SECONDS))
{
throw new SomeException("Timeout occurred while trying to acquire lock");
}
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
throw new SomeException("Interrupted", e);
}
}
#Override
public void close()
{
lock.unlock();
synchronized (mutex)
{
claimsPerLock.compute(key, (k, oldValue) -> oldValue == null ? 0 : --oldValue);
if (claimsPerLock.get(key) <= 0)
{
lockMap.remove(key);
claimsPerLock.remove(key);
}
}
}
}

Setting and accessing a varibale by two different threads

I have two threads, one setting a variable of a class, and the other one accessing the variable by a get method.
public class Parent {
private int value = -1
public int getValue()
return this.value;
}
public void setValue(int value){
this.value = value;
}
private class UpdatingVaribale extends Thread {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
setValue(2);
Thread.currentThread().interrupt();
}
}
}
}
private class GettingVaribale extends Thread {
public void run() {
while (getValue == -1) {
try{
System.out.println(getValue);
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
System.out.println(getValue);
}
}
The problem is that the condition of the while loop in the second thread is always true. The System.out.println(getValue) always prints -1. I am wondering why the second thread doesn't get the new value of value which is 2. I don't think the synchronized matters here since one thread is setting a variable and the other one just accessing the variable.
There are some solutions here:
use standard Java class AtomicInteger for storing your value in multi-threaded safe way. Actually it's the best and fastest way.
add synchronized keyword to your getValue and setValue methods
add volatile java keyword to i field definition
The source of your problem is i variable value actually looks different in different threads cause of CPU speed and memory optimization and you have to specify JVM somehow don't to do this optimization and - opposite - makes the latest i value visible in all threads.
UPDATE code for testing
public class SyncProblem {
public static void main(String[] args) {
Parent parent = new Parent();
new Thread(parent.new GettingVaribale()).start();
new Thread(parent.new UpdatingVaribale()).start();
}
}
class Parent {
private volatile int value = -1;
public int getValue() {
return this.value;
}
public void setValue(int value) {
this.value = value;
}
class UpdatingVaribale implements Runnable {
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
setValue(2);
Thread.currentThread().interrupt();
}
}
}
class GettingVaribale implements Runnable {
#Override
public void run() {
while (getValue() == -1) {
try {
System.out.println(getValue());
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
System.out.println(getValue());
}
}
}

All threads get locked in wait() state [duplicate]

This question already has answers here:
Notify not getting the thread out of wait state
(3 answers)
Closed 7 years ago.
Basically I have to create 3 classes (2 threaded).
First one holds some cargo (has a minimum capacity (0) and a maximum (200))
Second one supplies the cargo every 500ms.
Third one takes away from cargo every 500ms.
Main program has one cargo class(1), 2 supplier classes(2) and 2 substraction classes(3). Problem I'm having is that one by one, they're falling into a wait(); state and never get out. Eventually all of them get stucked in the wait() state, with the program running, but without them actually doing anything.
First class:
public class Storage {
private int maxCapacity;
private int currentCapacity;
public Storage( int currentCapacity, int maxCapacity ) {
this.currentCapacity = currentCapacity;
this.maxCapacity = maxCapacity;
}
public int getCapacity(){ return this.currentCapacity; }
public void increase( int q ) {
this.currentCapacity += q;
System.out.println("increase" + q + ". Total: " + currentCapacity);
}
public int getMax() { return this.maxCapacity; }
public void decrease( int q ) {
this.currentCapacity -= q;
System.out.println("decrease - " + q + ". Total: " + currentCapacity);
}
}
2nd class (supplier):
public class Supplier implements Runnable {
private int capacity;
private Storage storage;
private volatile boolean run;
public Supplier( int capacity, Storage storage ) {
this.capacity = capacity;
this.storage = storage;
this.run = true;
}
public void kiss_kill() { run = !run; }
public synchronized void add() {
while(storage.getCapacity() + capacity > storage.getMax()) {
try {
System.out.println("wait - supplier");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.increase(capacity);
notifyAll();
}
public void run() {
synchronized (this) {
while(run) {
add();
Thread.yield(); //would be wait(500), but this just speeds it up
}
}
}
}
3rd class (taker/demander):
public class Taker implements Runnable {
private int capacity;
private Storage storage;
private volatile boolean run;
public Taker( int capacity, Storage storage ) {
this.capacity = capacity;
this.storage = storage;
this.run = true;
}
public void kiss_kill() { run = !run; }
public synchronized void take() {
while(storage.getCapacity() - capacity < 0) {
try {
System.out.println("wait - taker");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
storage.decrease(capacity);
notifyAll();
}
public void run() {
synchronized (this) {
while(run) {
take();
Thread.yield(); //again, wait(500) should be instead
}
}
}
}
Main is something like this:
public class Main{
public static void main(String... args) {
Storage sk = new Storage(100, 200);
Supplier[] s = { new Supplier(10, sk), new Supplier(15, sk) };
Taker[] p = { new Taker(15, sk), new Taker(20, sk) };
Thread t[] = {
new Thread(s[0]),
new Thread(s[1]),
new Thread(p[0]),
new Thread(p[1]) };
for(Thread th : t) th.start();
try {
Thread.sleep(60000); //program should last for 60s.
} catch (InterruptedException e) {
e.printStackTrace();
}
s[0].kiss_kill(); s[1].kiss_kill(); p[0].kiss_kill(); p[1].kiss_kill();
}
}
Why doesn't notifyAll() release the wait() state of other object? What could I do to fix this?
Sorry, I know it's a long example, I hate posting too many classes like this. Thanks for reading!
I translated the code, so if you spot anything that you're unsure about that I've missed, please tell me and I'll fix it right away!
Doing concurrency is easy:
Anyone can slap synchronized on methods and synchronized () {} around blocks of code. It does not mean it is correct. And then they can continue to slap synchronized on everything until it works until it doesn't.
Doing concurrency correctly is Hard:
You should lock on the data that needs to be consistent not the methods making the changes. And you have to use the same lock instance for everything.
In this case that is the currentCapacity in Storage. That is the only thing that is shared and the only thing that needs to be consistent.
What you are doing now is having the classes lock on instances of themselves which means nothing shared is being protected because there is no shared lock.
Think about it, if you are not locking on the same exact instance which must be final of an object then what are you protecting?
Also what about code that has access to the object that needs to be consistent and does not request a lock on it. Well it just does what it wants. synchronized() {} in calling classes is not how you protect shared data from external manipulation.
Thread safe objects are NOT about the synchronized keyword:
Read up on the java.util.concurrent package it has all the things you need already. Use the correct data structure for your use case.
In this particular case if you use AtomicInteger for your counter, you do not need any error prone manual locking, no need for synchronized anywhere, it is already thread safe.
Immutable Data:
If you work with immutable data exclusively you do not need any of this silly locking semantics that are extremely error prone for even those that understand it and even more so for those that think they understand it.
Here is a working idiomatic example:
This is a good chance to learn what non-deterministic means and how to use the step debugger in your IDE to debug concurrent programs.
Q33700412.java
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import com.vertigrated.FormattedRuntimeException;
public class Q33700412
{
public static void main(final String[] args)
{
final Storage s = new Storage(100);
final int ap = Runtime.getRuntime().availableProcessors();
final ExecutorService es = Executors.newFixedThreadPool(ap);
for (int i = 0; i < ap; i++)
{
es.execute(new Runnable()
{
final Random r = new Random();
#Override
public void run()
{
while (true)
{
/* this if/else block is NOT thread safe, I did this on purpose
the state can change between s.remainingCapacity() and
the call to s.increase/s.decrease.
This is ok, because the Storage object is internally consistent.
This thread might fail if this happens, this is the educational part.
*/
if (s.remainingCapacity() > 0)
{
if (r.nextBoolean()) { s.increase(r.nextInt(10)); }
else { s.decrease(10); }
System.out.format("Current Capacity is %d", s.getCurrentCapacity());
System.out.println();
}
else
{
System.out.format("Max Capacity %d Reached", s.getMaxCapacity());
System.out.println();
}
try { Thread.sleep(r.nextInt(5000)); }
catch (InterruptedException e) { throw new RuntimeException(e); }
}
}
});
}
es.shutdown();
try
{
Thread.sleep(TimeUnit.MINUTES.toMillis(1));
es.shutdown();
}
catch (InterruptedException e) { System.out.println("Done!"); }
}
public static final class Storage
{
/* AtomicInteger is used so that it can be mutable and final at the same time */
private final AtomicInteger currentCapacity;
private final int maxCapacity;
public Storage(final int maxCapacity) { this(0, maxCapacity); }
public Storage(final int currentCapacity, final int maxCapacity)
{
this.currentCapacity = new AtomicInteger(currentCapacity);
this.maxCapacity = maxCapacity;
}
public int remainingCapacity() { return this.maxCapacity - this.currentCapacity.get(); }
public int getCurrentCapacity() { return this.currentCapacity.get(); }
public void increase(final int q)
{
synchronized (this.currentCapacity)
{
if (this.currentCapacity.get() < this.maxCapacity)
{
this.currentCapacity.addAndGet(q);
}
else
{
throw new FormattedRuntimeException("Max Capacity %d Exceeded!", this.maxCapacity);
}
}
}
public int getMaxCapacity() { return this.maxCapacity; }
public void decrease(final int q)
{
synchronized (this.currentCapacity)
{
if (this.currentCapacity.get() - q >= 0)
{
this.currentCapacity.addAndGet(q * -1);
}
else
{
this.currentCapacity.set(0);
}
}
}
}
}
Notes:
Limit the scope of synchronized blocks to the minimum they need to protect and lock on the object that needs to stay consistent.
The lock object must be marked final or the reference can change and you will be locking on different instances.
The more final the more correct your programs are likely to be the first time.
Jarrod Roberson gave you the "how" half of the answer. Here's the other half--the "why".
Your Supplier object's add() method waits on itself (i.e., on the supplier object), and it notifies itself.
Your Taker object's take() method waits on its self (i.e., on the taker object), and it notifies its self.
The supplier never notifies the taker, and taker never notifies the supplier.
You should do all of your synchronization on the shared object (i.e., on the Storage object.
So I should convert storage into a thread?
No, you don't want Storage to be a thread, you want it to be the lock. Instead of having your Supplier objects and your Taker objects synchronize on themselves, they should all synchronize on the shared Storage object.
E.g., do this:
public void take() {
synchronized(storage) {
while(...) {
try {
storage.wait();
} catch ...
}
...
storage.notifyAll();
}
}
Instead of this:
public synchronized void take() {
while(...) {
try {
wait();
} catch ...
}
...
notifyAll();
}
And do the same for all of your other synchronized methods.

PriorityQueue and PriorityBlockingQueue

which one should I choose over another among these programs and why? Generally the question is why should I choose to use PriorityBlockingQueue over PriorityQueue.
PriorityBlockingQueue
import java.util.concurrent.PriorityBlockingQueue;
public class PriorityBlockingQueueExample {
static PriorityBlockingQueue<String> priorityQueue = new PriorityBlockingQueue<String>();
public static void main(String[] args) {
new Thread(){
public void run(){
try {
System.out.println(priorityQueue.take() +" is removed from priorityQueue object");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
new Thread(){
public void run(){
priorityQueue.add("string variable");
System.out.println("Added an element to the queue");
}
}.start();
}
}
which one should I choose over another among these programs and why? Generally the question is why should I choose to use PriorityBlockingQueue over PriorityQueue.
PriorityQueue
import java.util.PriorityQueue;
public class PriorityQueueTest {
static PriorityQueue<String> priorityQueue = new PriorityQueue<String>();
private static Object lock = new Object();
public static void main(String[] args) {
new Thread(){
public void run(){
synchronized(lock){
try {
while(priorityQueue.isEmpty()){lock.wait();}
System.out.println(priorityQueue.remove() +" is removed from priorityQueue object");
lock.notify();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}.start();
new Thread(){
public void run(){
synchronized(lock){
priorityQueue.add("string variable");
System.out.println("Added an element to the queue");
lock.notify();
}
}
}.start();
}
}
A normal Queue will return null when accessed if it is empty, while a BlockingQueue blocks if the queue is empty until a value is available.
The priority part in the queues you are using simply means the items are read from the queue in a specific order (either natural if they implement Comparable or according to a Comparator).
Typically you could should depend on the abstract type, either PriorityQueue or BlockingQueue. If your code requires knowledge of both these concepts a re-think may be needed.
There's numerous reasons why you might need a PriorityQueue that boil down to message ordering. For example on a queue of jobs, you might want to be able to give those jobs priority. That said typically the code processing the jobs should be agnostic to the order.
With a BlockingQueue you're typically in the realm of worker threads picking up queued work and when there's no work to do, those threads can be blocked until work becomes available. Like the example of a PriorityQueue, the calling code could be agnostic to this, though as you may want to use some sort of wait timeout that's not always case.
PriorityBlockingQueue was added with the concurrent package in JDK 5 see: http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/package-summary.html
It's basically under the hood doing the extra code you wrote for PriorityQueue of adding the commonly necessary synchronize/wait/notify around your queue. Thus the "Blocking" part of the name is added to imply the thread will block waiting until there's an item available on the queue.
If your app can run on JDK 5 or newer, I'd use PriorityBlockingQueue.
I know that this is an old topic but I saw that you didnt consider a concurrent implementation of a priority queue.
Although java's collections framework does not have one, it does have enough building blocks to create one:
public class ConcurrentSkipListPriorityQueue<T> implements Queue<T> {
private ConcurrentSkipListMap<T, Boolean> values;
public ConcurrentSkipListPriorityQueue(Comparator<? super T> comparator) {
values = new ConcurrentSkipListMap<>(comparator);
}
public ConcurrentSkipListPriorityQueue() {
values = new ConcurrentSkipListMap<>();
}
#Override
public boolean add(T e) {
values.put(e, Boolean.TRUE);
return true;
}
#Override
public boolean offer(T e) {
return add(e);
}
#Override
public T remove() {
while (true) {
final T v = values.firstKey();
if (values.remove(v)) {
return v;
}
}
}
#Override
public T poll() {
try {
while (true) {
if (values.isEmpty()) {
return null;
}
final T v = values.firstKey();
if (values.remove(v)) {
return v;
}
}
} catch (NoSuchElementException ex) {
return null; // poll should not throw an exception..
}
}
#Override
public T element() {
return values.firstKey();
}
#Override
public T peek() {
if (values.isEmpty()) {
return null;
}
try {
return element();
} catch (NoSuchElementException ex) {
return null;
}
}
#Override
public int size() {
return values.size();
}
#Override
public boolean isEmpty() {
return values.isEmpty();
}
#Override
public boolean contains(Object o) {
return values.containsKey(o);
}
#Override
public Iterator<T> iterator() {
return values.keySet().iterator();
}
#Override
public Object[] toArray() {
return values.keySet().toArray();
}
#Override
public <T> T[] toArray(T[] a) {
return values.keySet().toArray(a);
}
#Override
public boolean remove(Object o) {
return values.remove(o);
}
#Override
public boolean containsAll(Collection<?> c) {
return values.keySet().containsAll(c);
}
#Override
public boolean addAll(Collection<? extends T> c) {
boolean changed = false;
for (T i : c) {
changed |= add(i);
}
return changed;
}
#Override
public boolean removeAll(Collection<?> c) {
return values.keySet().removeAll(c);
}
#Override
public boolean retainAll(Collection<?> c) {
return values.keySet().retainAll(c);
}
#Override
public void clear() {
values.clear();
}
}
This queue is based on skip list by delegating all of its operations to the ConcurrentSkipListMap class. It allows non-blocking concurrent access from multiple threads.

Categories