You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JNA回调方法仅在FutureTask.get()超时时才触发是什么原因?

问题成因

这是线程调度层面的互相等待问题,不属于Java对象监视器的死锁,核心原因如下:

  • 厂商SDK的回调派发逻辑限制:绝大多数摄像头类硬件的Native SDK,默认会把回调事件绑定到login方法的调用线程,依赖调用线程的空闲状态/内部消息队列来派发回调。你调用无参futureTask.get()时,当前线程直接进入永久阻塞状态,没有机会处理SDK内部的回调消息,因此回调代码块永远不会执行,形成「线程等回调执行future -> 回调等线程空闲才能派发」的僵持状态。
  • 超时get的行为差异:使用带超时参数的get方法时,1秒后方法会抛出TimeoutException,当前线程从阻塞状态被唤醒恢复执行,此时线程处于可处理消息的空闲状态,SDK排队的回调事件就可以正常派发执行,所以会出现超时后回调反而被触发的现象。
修复方案
  • 方案1:单独启动子线程执行login方法,不要阻塞回调依赖的调用线程
FutureTask<Long> futureTask = new FutureTask<>(System::currentTimeMillis);
// 独立线程执行登录逻辑,不阻塞当前线程的消息处理
new Thread(() -> CameraSDk.login(ip, port, userName, password, 
       (lLoginID, pBuf, RevLen, EncodeType, CmdSerial, dwUser) -> {
    // 回调处理逻辑
    futureTask.run();
})).start();

try {
    Long timestamp = futureTask.get();
    System.out.println("timestamp = " + timestamp);
} catch (InterruptedException | ExecutionException e) {
    e.printStackTrace();
}
  • 方案2:查询对应SDK的开发文档,将回调派发模式修改为独立线程派发,不需要绑定login调用线程的状态。
  • 方案3:如果是Windows平台的SDK,确保login调用线程没有被长期阻塞,按文档要求定期处理消息循环。

内容的提问来源于stack exchange,提问作者King K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 23:27:03