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

烈酒焚心 提交于 2019-12-10 04:33:05

问题


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.


回答1:


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.




回答2:


Firt you need to use the take method. This method will block while the queue is empty. THis will replace your check to see if the queue is empty.

Second, why do you need a timestamp? If the timestamp is to make sure you process the requests int he order that they were put into the queue then you do not need it, as the queue is FIFO and made for concurrent multithreaded environment. If the timestamp is from outside of the system, some external timestamp, where the requests might come out of order but then need to be processed in order, then this BlockQueue will not cut it. You might need a PriorityBlockingQueue where you will prioritize the requests by timestamp. So either get rid of the timestamp or use a PriorityBlockingQueue.



来源:https://stackoverflow.com/questions/31608988/java-thread-producer-consumer-what-is-the-most-efficient-way-to-wait-for-data-t

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!