Java PriorityBlockingQueue extend

Description

Java PriorityBlockingQueue extend

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TransferQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantLock;

class Resource<E> extends PriorityBlockingQueue<E> implements TransferQueue<E> {
  private AtomicInteger counter = new AtomicInteger(0);
  private LinkedBlockingQueue<E> transfered = new LinkedBlockingQueue<>();
  private ReentrantLock lock = new ReentrantLock();

  @Override/* w  w w  . j  a v a  2s.c  o  m*/
  public boolean tryTransfer(E e) {
    lock.lock();
    boolean value;
    if (counter.get() == 0) {
      value = false;
    } else {
      put(e);
      value = true;
    }
    lock.unlock();
    return value;
  }

  @Override
  public void transfer(E e) throws InterruptedException {
    lock.lock();
    if (counter.get() != 0) {
      put(e);
      lock.unlock();
    } else {
      transfered.add(e);
      lock.unlock();
      synchronized (e) {
        e.wait();
      }
    }
  }

  @Override
  public boolean tryTransfer(E e, long timeout, TimeUnit unit) throws InterruptedException {
    lock.lock();
    if (counter.get() != 0) {
      put(e);
      lock.unlock();
      return true;
    } else {
      transfered.add(e);
      long newTimeout = TimeUnit.MILLISECONDS.convert(timeout, unit);
      lock.unlock();
      e.wait(newTimeout);
      lock.lock();
      if (transfered.contains(e)) {
        transfered.remove(e);
        lock.unlock();
        return false;
      } else {
        lock.unlock();
        return true;
      }
    }
  }

  @Override
  public boolean hasWaitingConsumer() {
    return (counter.get() != 0);
  }

  @Override
  public int getWaitingConsumerCount() {
    return counter.get();
  }

  @Override
  public E take() throws InterruptedException {
    lock.lock();
    counter.incrementAndGet();
    E value = transfered.poll();
    if (value == null) {
      lock.unlock();
      value = super.take();
      lock.lock();
    } else {
      synchronized (value) {
        value.notify();
      }
    }
    counter.decrementAndGet();
    lock.unlock();
    return value;
  }
}

class Consumer implements Runnable {
  private Resource<Event> buffer;

  public Consumer(Resource<Event> buffer) {
    this.buffer = buffer;
  }

  @Override
  public void run() {
    for (int i = 0; i < 1000; i++) {
      try {
        Event value = buffer.take();
        System.out.printf("Consumer: %s: %d\n", value.getThread(), value.getPriority());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

}

class Producer implements Runnable {
  private Resource<Event> buffer;

  public Producer(Resource<Event> buffer) {
    this.buffer = buffer;
  }

  @Override
  public void run() {
    for (int i = 0; i < 100; i++) {
      Event event = new Event(Thread.currentThread().getName(), i);
      buffer.put(event);
    }
  }
}

class Event implements Comparable<Event> {
  private String thread;
  private int priority;

  public Event(String thread, int priority) {
    this.thread = thread;
    this.priority = priority;
  }

  public String getThread() {
    return thread;
  }

  public int getPriority() {
    return priority;
  }

  @Override
  public int compareTo(Event e) {
    if (this.priority > e.getPriority()) {
      return -1;
    } else if (this.priority < e.getPriority()) {
      return 1;
    } else {
      return 0;
    }
  }
}

public class Main {
  public static void main(String[] args) throws Exception {
    Resource<Event> buffer = new Resource<>();
    Producer producer = new Producer(buffer);
    Thread producerThreads[] = new Thread[10];
    for (int i = 0; i < producerThreads.length; i++) {
      producerThreads[i] = new Thread(producer);
      producerThreads[i].start();
    }
    Consumer consumer = new Consumer(buffer);
    Thread consumerThread = new Thread(consumer);
    consumerThread.start();
    System.out.printf("Consumer count: %d\n", buffer.getWaitingConsumerCount());
    Event myEvent = new Event("Core Event", 0);
    buffer.transfer(myEvent);
    for (int i = 0; i < producerThreads.length; i++) {
      producerThreads[i].join();
    }
    TimeUnit.SECONDS.sleep(1);
    System.out.printf("Consumer count: %d\n", buffer.getWaitingConsumerCount());
    myEvent = new Event("Core Event 2", 0);
    buffer.transfer(myEvent);
    consumerThread.join();
  }
}



PreviousNext

Related