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

Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82
perkss
  • 1,037
  • 1
  • 11
  • 37
  • 1
    Put the intermediate results in a `BlockingQueue` instead of returning the result and have other threads get these results from the queue. – Chetan Kinger Jul 24 '15 at 08:28

2 Answers2

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.

ZeroOne
  • 3,041
  • 3
  • 31
  • 52
Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82
  • 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 cycles – Stef Jul 24 '15 at 09:42
  • @Stef 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. – Chetan Kinger Jul 24 '15 at 09:53
  • 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? – Stef Jul 24 '15 at 10:06
  • @Stef 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.. – Chetan Kinger Jul 24 '15 at 10:07
  • 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. – perkss Jul 24 '15 at 10:18
  • 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. – Chetan Kinger Jul 24 '15 at 10:32
  • 1
    New post: http://stackoverflow.com/questions/31608988/java-thread-producer-consumer-what-is-the-most-efficient-way-to-wait-for-data-t @Stef – perkss Jul 24 '15 at 11:07
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.

Geek
  • 23,089
  • 20
  • 71
  • 85