使用Java期货处理远程事件

时间:2016-10-14 18:16:54

标签: java concurrency completable-future

我使用Java编程与微控制器进行RPC风格的通信。我面临的问题是阻止客户端代码执行,直到我收到微控制器的结果,这是非同步的。

即,我发出命令并在两个不同的线程(相同的类)中接收结果。我采用的方法是使用CompletableFuture,但这并不像我预期的那样有效。

我的RPC调用方法发出命令并实例化CompletableFuture,如下所示:

pygame.display.set_mode((w, h))

在看起来像这样的调用代码中:

protected synchronized CompletableFuture<String> sendCommand(String command) {
    ... send command ...

    this.handler = new CompletableFuture<String>();

    return this.handler;
}

接下来,有一个从微控制器接收数据的监听方法:

CompletableFuture<String> result = procedure.sendCommand("readSensor(0x1508)");
String result = result.get(5, TimeUnit.SECONDS); // line X

我希望客户端代码执行将在X行阻塞,它确实会这样做。但由于某种原因,行Y不会解除阻塞,导致超时异常。

回答以下评论......

致电代码(对不起,名字与我上面提供的内容完全不符,但我认为这是唯一的区别):

protected synchronized void onReceiveResult(String data) {
    this.handler.complete(data); // line Y
}

产生输出:

CompletableFuture<String> result = this.device.sendCommand(cmd);
log.debug("Waiting for callback, result=" + result);
String sid = result.get(timeout, unit);

完成代码:

2016-10-14 21:58:30 DEBUG RemoteProcedure:36 - Waiting for callback, result=com.***.rpc.RemoteDevice$ActiveProcedure@44c519a2[Not completed]

产生输出:

log.debug("Dispatching msg [" + msg + "] to a procedure: " + this.commandForResult);
log.debug("result=" + this.result);
log.debug("Cancelled = " + this.result.isCancelled());
log.debug("Done = " + this.result.isDone());
log.debug("CompletedExceptionally = " + this.result.isCompletedExceptionally());

boolean b = this.result.complete(msg);
this.result = null;

log.debug("b=" + b);

ActiveProcedure是实际的CompletableFuture:

2016-10-14 21:58:35 DEBUG RemoteDevice:141 - Dispatching msg [123] to a procedure: getId;
2016-10-14 21:58:35 DEBUG RemoteDevice:142 - result=com.***.rpc.RemoteDevice$ActiveProcedure@44c519a2[Not completed]
2016-10-14 21:58:35 DEBUG RemoteDevice:143 - Cancelled = false
2016-10-14 21:58:35 DEBUG RemoteDevice:144 - Done = false
2016-10-14 21:58:35 DEBUG RemoteDevice:145 - CompletedExceptionally = false
2016-10-14 21:58:35 DEBUG RemoteDevice:150 - b=true

1 个答案:

答案 0 :(得分:0)

确定。事情很清楚:

底层库存在集成问题,我用它来与微控制器通信。我希望我在一个单独的线程中从设备接收数据,但这发生在同一个线程中。因此CompletableFuture.get没有取消阻止。

我不完全理解导致此类行为的机制,但放置

handler.complete(msg);

进入一个单独的线程解决了这个问题。