简体   繁体   中英

Could Java(Scala) blocking queue allows queue jumper(higher priority)?

One could use LinkedBlockingQueue to block the operations. Suppose I have only 1 element in queue, and every one could use it.

val q = new LinkedBlockingQueue() // 1 element in it
def fun() = {
  val instance = q.take()
  // do some operations
}
def foo() = {
  val instance = q.take()
  // do some operations
}
// Use 3 threads to run following 3 methods, and the order they call q.take() is following
fun()
fun() // will wait for first fun()
foo() // will wait for second fun()

And the sequential order these methods finish is fun(), fun(), foo()

However, now I want to set foo to higher priority, which means allow it to be queue-jumper. That the foo could take instance before the second fun() (while the second fun is waiting, foo jumps to the front of it)

And the order they finish could become fun(), foo(), fun() , (the first fun would take the instance because the instance is available, and second should wait, then the foo also wait, but jumped to the front of second fun )

Is is possible? Or is there any other data structure possible for this

I don't know of any built-in tool for this task, but it wouldn't be too hard to implement. Since you only want to exchange a single element, you don't need a queue but an exchanger.

A simple implementation could look like

class SingleElementExchanger<T> {
    int priorityConsumer;
    T value;

    public synchronized void set(T newValue) throws InterruptedException {
        Objects.requireNonNull(newValue);
        while(value != null) wait();
        value = newValue;
        notifyAll();
    }

    public synchronized T ordinaryGet() throws InterruptedException {
        while(priorityConsumer != 0 || value == null) wait();
        T received = value;
        value = null;
        notifyAll();
        return received;
    }

    public synchronized T priorityGet() throws InterruptedException {
        priorityConsumer++;
        try {
            while(value == null) wait();
            T received = value;
            value = null;
            notifyAll();
            return received;
        }
        finally {
            priorityConsumer--;
        }
    }
}

For your two ordinary consumers and one priority consumer and a small number of producers, this might already be sufficient.

For a larger number of threads, you might want to use a Lock , to be able to notify the right party instead of using notifyAll() .

class SingleElementExchanger<T> {
    final Lock lock = new ReentrantLock();
    final Condition empty = lock.newCondition(),
        fullNoPri = lock.newCondition(), fullPri = lock.newCondition();

    int priorityConsumer;
    T value;

    public void set(T newValue) throws InterruptedException {
        Objects.requireNonNull(newValue);
        lock.lock();
        try {
            while(value != null) empty.await();
            value = newValue;
            (priorityConsumer==0? fullNoPri: fullPri).signal();
        }
        finally {
            lock.unlock();
        }
    }

    public T ordinaryGet() throws InterruptedException {
        lock.lock();
        try {
            while(priorityConsumer != 0 || value == null) fullNoPri.await();
            T received = value;
            value = null;
            empty.signal();
            return received;
        }
        finally {
            lock.unlock();
        }
    }

    public T priorityGet() throws InterruptedException {
        lock.lock();
        try {
            priorityConsumer++;
            while(value == null) fullPri.await();
            T received = value;
            value = null;
            empty.signal();
            return received;
        }
        finally {
            priorityConsumer--;
            lock.unlock();
        }
    }
}

You need to look up CompletableFuture for your purpose. This way you can achieve task ordering.

CompletableFuture<String> text = CompletableFuture.supplyAsync(() -> {
    return "";
}).thenApply(param -> {
    return "";
}).thenApply(param -> {
    return "";
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM