Search code examples
javamultithreadingasynchronousblockingthread-sleep

Java8 - Converting an async interface into a synchronous one


I am working with an external lib that defines a Monitor class that accepts a Sensor interface and sends results into it periodically:

public interface Sensor {
    // called by the monitor when new results are available
    void updatedResult(double result);

    // called when done sending results
    void done();
}

I have implemented the sensor as follows:

public class SensorImpl implements Sensor {
    private boolean isDone;
    private List<double> data;

    public SensorImpl() {
        this.isDone = false;
        this.data = new ArrayList<>();
    }

    @Override
    void updatedResult(double result);
        this.data.add(result);
    }

    @Override
    void done() {
        this.isDone = true;
    }

    public boolean isDoneReceiving() {
        return this.isDone;
    }

    public List<double> getData() {
        return this.data;
    }
}

And am running my program like this (simplified):

  public void run() {

    // initialize a sensor instance
    SensorImpl sensor = new SensorImpl();

    // initialize a monitor that streams data into the sensor (async)
    Monitor monitor = new Monitor(sensor);

    // start monitoring the sensor
    monitor.start();

    // block until done
    while (!sensor.isDoneReceiving()) {
        Thread.sleep(50);
    }

    // retrieve data and continue processing...
    List<double> data = sensor.getData();

    // ...
}

While this works, it feels icky to be blocking on a thread with sleep, and I'm looking for a way to make this cleaner. This becomes even more relevant when applying executors to monitor multiple sensors of various types in parallel. Any assistance will be appreciated.

UPDATE:

I ended up implementing Future<List<Double>>, which allowed me to simply call List<Double> results = sensor.get();, which blocks until all results are available.

public class SensorImpl implements Sensor {

    // ...
    private CountDownLatch countDownLatch;

    public SensorImpl() {
        this.countDownLatch = new CountDownLatch(1);
    }

    // ...

    @Override
    public void done() {
        // when called by async processes, decrement the latch (and release it)
        this.countDownLatch.countDown();
    }

    // ...

}

Here's a great answer that provided good reference: https://stackoverflow.com/a/2180534/187907


Solution

  • In your case, several classes from the concurrent package can help you, such as Semaphore, CoundDownLatch, CyclicBarrier or even a BlockingQueue, where you would block on the queue and wait for the other threads to put values in it when finished.

    A CountDownLatch is most probably best suited for your specific example. Perhaps you can view this question, it has a nice overview about Semaphore and CountDownLatch: