Java : How to return intermediate results from a Thread
Asked Answered
S

2

7

Using Java 7 I am trying to build a watcher that watches a data store (some collection type) and then will return certain items from it at certain points. In this case they are time stamps, when a timestamp passes the current time I want it to be returned to the starting thread. Please see code below.

@Override
public void run() {
  while (!data.isEmpty()) {
    for (LocalTime dataTime : data) {
      if (new LocalTime().isAfter(dataTime)) {
        // return a result but continue running
      }
    }
  }
}

I have read about future and callables, but they seem to stop the thread on a return.

I do not particularly want to return a value and stop the thread then start another task if using callable, unless it is the best way.

What are the best techniques to look for this? There seem to be such a wide range of doing it.

Thanks

Schram answered 24/7, 2015 at 8:25 Comment(1)
Put the intermediate results in a BlockingQueue instead of returning the result and have other threads get these results from the queue.Faizabad
F
6

You can put the intermediate results in a Blocking Queue so that the results are available to consumer threads as and when they are made available :

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);
      }
    }
  }
}

public Result takeResult() {
    return results.take(); 
}

Consumer threads can simply call the takeResult method to use the intermediate results. The advantage of using a Blocking Queue is that you don't have to reinvent the wheel since this looks like a typical producer-consumer scenario that can be solved using a blocking data structure.

Note Here, Result can be a `POJO that represents the intermediate result object.

Faizabad answered 24/7, 2015 at 8:31 Comment(7)
The loop in this run() method will consume a lot of resources. You should wait for the next dataTime using object.wait instead of just using up cyclesNorean
@Norean The !data.isEmpty() condition will exit the loop when there is no data available. It seems to me that the data to be consumed is already populated in one go instead of populating it one by one.Faizabad
Yes if all the data is processed you exit cleanly. But what if there is one element in data that is supposed to be returned 10 minutes from now?Norean
@Norean There are a lot of scenarios you can bring up. The question is whether they are valid in the context of this question. I believe your scenario is not valid in this context because the code will exit if there is no data even for a nanosecond. And using object.wait would not be an ideal solution either way..Faizabad
This is an interesting point, as now moving on with it, the data list, will actually be added to and removed from. So what would be an efficient way of checking? Instead of .isEmpty(). And why wouldnt object.wait. But this is out of scope of my original question.Schram
Make data a blocking collection as well and use while(data.take()!=null) { } . That said, I don't recommend that you edit this question with this new requirement. Instead, post a new question with this requirement.Faizabad
New post: #31609488 @NoreanSchram
I
1

You are on the right path. Assuming proper synchronization will be there and you will be getting all your timestamps on time :) You should ideally choose a data structure that doesn't require you to scan through all the items. Choose something like a min heap or some ascending/descending lists and now when you iterate just delete the element from this data store and put it on a Blocking Queue. have a thread that is listening on this queue to proceed further.

Insecurity answered 24/7, 2015 at 8:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.