【发布时间】:2017-01-25 17:36:30
【问题描述】:
我有一个记录器类,它每 n 毫秒从数据源轮询一次值。整个 this 应该是异步运行并返回一个包含记录数据的集合。
我的想法是拥有一个带有单线程的 ExecutorService 和一个执行数据轮询的 Callable。可调用对象应该被中断,因此调用者不必等待任何Thread.sleep 调用完成。为了打断他 Callable,我在 ExecutorService 返回的 Future 上调用 Future.cancel(true):
class Recorder {
private DataSource source;
private ExecutorService executor;
private Future<List<MyData>> dataFuture;
private class FixedPollRateCallable {
private DataSource source;
private long pollrate;
public FixedPollrateCallable(DataSource source, long pollrate) {
this.source = source;
this.pollrate = pollrate;
}
public List<MyData> call() throws Exception {
List<MyData> dataList = new ArrayList<>();
while(!Thread.currentThread().isInterrupted()) {
dataList.add(source.getData());
try {
Thread.sleep(pollrate);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
return dataList;
}
}
public Recorder(DataSource source) {
this.source = source;
this.executor = Executors.newSingleThreadExecutor();
}
public void startRecording(long pollrate) {
if(dataFuture != null && !dataFuture.isDone())
throw new RecordingException();
dataFuture = executor.submit(new FixedPollRateCallable(source, pollrate);
}
public void stopRecording() {
dataFuture.cancel(true);
}
public List<MyData> getRecordedData() throws InterruptedException, ExecutionException {
return dataFuture.get();
}
}
但是当这样调用整个事情时:
recorder.startRecording();
recorder.stopRecording();
recorder.getRecordedData();
我在recorder.getRecordedData() 通话中收到java.util.concurrent.CancellationException。
我猜cancel(true)除了中断线程外,还设置了一个取消标志,所以对Future.get()的调用总是会失败。
有什么办法可以解决这个问题,或者你知道一个更好的替代方案,可以让我中断线程,突破Thread.sleep() 并且仍然能够返回一个值?
【问题讨论】:
标签: java multithreading