Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Thread producer consumer what is the most efficient way to wait for data to be produced

When using BlockingQueue to consume data that is produced what is the most efficient method for waiting for the data to appear?

Scenario:

Step 1) The data list will be a data store where timestamps are added to. These timestamps are required to be ordered by closest to current time priority. This list may be empty. A thread will be inserting the timestamps into it. Produce

Step 2) I want to consume the data in here in another thread that will take the timestamps from data and check if they are after the current time. Consumer then Produce

Step 3) If they are after the current time then send them on to another thread to be consumed and processed. Once the time stamp data is processed here, remove from the Step 1 data store. Consume then edit the original list.

In the below code the data field refers to the data store in step 1. The results is the list of timestamps that have been sent that are after the current time. Step 2. The results will then be consumed step 3.

private BlockingQueue<LocalTime> data;
private final LinkedBlockingQueue<Result> results = new LinkedBlockingQueue<Result>();

@Override
public void run() {
  while (!data.isEmpty()) {
    for (LocalTime dataTime : data) {
      if (new LocalTime().isAfter(dataTime)) {
        results.put(result);
      }
    }
  }
}

Questions What is the most efficient way to wait for data to be added in the data list that could be potentially empty? Focus on:

while (!data.isEmpty())

Following from an earlier question.

like image 556
perkss Avatar asked Jul 24 '15 11:07

perkss


People also ask

How can we solve consumer problem by using wait () and notify () method?

You can use wait, notify, and notifyAll methods to communicate between threads in Java. For example, if you have two threads running in your programs like Producer and Consumer then the producer thread can communicate to the consumer that it can start consuming now because there are items to consume in the queue.

What are the different ways to solve producer-consumer problem in Java?

We can solve the producer-consumer problem using semaphores, Semaphore is a thread synchronization construct. Semaphore is used to control the access to a shared resource with the help of a variable/counter. The other way to solve this is using a thread. A thread is a sequential flow of control in a program.

What is producer-consumer problem explain the function wait () and notify ()?

In computing, the producer-consumer problem (also known as the bounded-buffer problem) is a classic example of a multi-process synchronization problem. The problem describes two processes, the producer and the consumer, which share a common, fixed-size buffer used as a queue.

What are the solutions to a producer-consumer problem?

The solution of Producer-Consumer Problem using Semaphore Binary Semaphore: In Binary Semaphore, only two processes can compete to enter into its CRITICAL SECTION at any point in time, apart from this the condition of mutual exclusion is also preserved.


1 Answers

what is the most efficient way to wait for data to be produced

The BlockingQueue has blocking functionality which will suspend threads waiting for a queue to be not empty or not full. In your case you are spinning on the queue which consume CPU. This is not preferred.

You should use take.

Suspending retrieves and removes the head of this queue, waiting if necessary until an element becomes available.

BlockingQueue#take

This will be the most efficient way to wait for elements from a queue as suspending threads consume no cpu. Once a new item is put on the queue the waiting threads will be woken.

Then you can use put which has the same waiting semantics as take but only if the queue is not full.

public void run(){
   LocalTime timestamp = null;
   while((timestamp = data.take()) != null){
      ...
   }
}

Updating based on our comments:

But in this case the timestamps are created in a sequential order and added. But a timestamp may be less in the future. E.g. Head node is 2 mins in future, Second node is 1 min, so the second node wants processing first

Then my follow up:

So you need priority queuing based on the timestamp of the LocalDate?

Not sure if you are using the LocalDate from JodaTime or Java 8, let's assume the latter.

You can use a PriorityBlockingQueue with the same blocking semantics. However, the priority aspect of a BlockingQueue will enqueue elements based on whatever order is defined. In your case, using the LocalDate you can have elements ordered from oldest-to-youngest or youngest-to-oldest.

BlockingQueue<LocalDate> data = new PriorityBlockingQueue<>(); 

OR INVERSE THE ORDER

BlockingQueue<LocalDate> data = new PriorityBlockingQueue<>(0, (a,b) -> b.compareTo(a));

In this case, you will process LocalDate in their natural order and not the order in which they are enqueued.

If you are using JodaTime's LocalDate you may need to implement your own Comparator similar to my second example.

EDIT: just realized you had this tagged as java-7. So you will use the JodaTime and if the JodaTime LocalDate does not implement Comparable, just create your own.

like image 183
John Vint Avatar answered Sep 28 '22 13:09

John Vint