Java8 - 将异步接口转换为同步接口
Java8 - Converting an async interface into a synchronous one
我正在使用一个外部库,它定义了一个 Monitor
class,它接受一个 Sensor
接口并定期向其中发送结果:
public interface Sensor {
// called by the monitor when new results are available
void updatedResult(double result);
// called when done sending results
void done();
}
我按如下方式实现了传感器:
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;
}
}
运行 我的程序是这样的(简化版):
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();
// ...
}
虽然这可行,但在线程上阻塞睡眠感觉很恶心,我正在寻找一种方法来使它更干净。当应用执行器并行监视各种类型的多个传感器时,这变得更加相关。如有任何帮助,我们将不胜感激。
更新:
我最终实现了 Future<List<Double>>
,这让我可以简单地调用 List<Double> results = sensor.get();
,直到所有结果都可用为止。
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();
}
// ...
}
这里有一个很好的答案,提供了很好的参考:
对于您的情况,concurrent
包中的几个 类 可以帮助您,例如 Semaphore
、CoundDownLatch
、CyclicBarrier
甚至 BlockingQueue
,您将在队列中阻塞并等待其他线程在完成后将值放入其中。
CountDownLatch 很可能最适合您的特定示例。
也许你可以查看 this question,它对信号量和 CountDownLatch 有一个很好的概述:
我正在使用一个外部库,它定义了一个 Monitor
class,它接受一个 Sensor
接口并定期向其中发送结果:
public interface Sensor {
// called by the monitor when new results are available
void updatedResult(double result);
// called when done sending results
void done();
}
我按如下方式实现了传感器:
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;
}
}
运行 我的程序是这样的(简化版):
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();
// ...
}
虽然这可行,但在线程上阻塞睡眠感觉很恶心,我正在寻找一种方法来使它更干净。当应用执行器并行监视各种类型的多个传感器时,这变得更加相关。如有任何帮助,我们将不胜感激。
更新:
我最终实现了 Future<List<Double>>
,这让我可以简单地调用 List<Double> results = sensor.get();
,直到所有结果都可用为止。
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();
}
// ...
}
这里有一个很好的答案,提供了很好的参考:
对于您的情况,concurrent
包中的几个 类 可以帮助您,例如 Semaphore
、CoundDownLatch
、CyclicBarrier
甚至 BlockingQueue
,您将在队列中阻塞并等待其他线程在完成后将值放入其中。
CountDownLatch 很可能最适合您的特定示例。 也许你可以查看 this question,它对信号量和 CountDownLatch 有一个很好的概述: