我正在尝试使用正在处理给定请求的第三方内部库。不幸的是,它本质上是同步的。此外,我无法控制相同的代码。基本上它是一个函数调用。这个功能在行为上似乎有些不稳定。有时此功能需要10毫秒才能完成处理,有时需要300秒来处理请求。
你能否建议我在这个函数周围编写一个包装器,这样如果函数没有用x ms / secs完成处理,就会抛出一个中断的异常。我可以忍受没有结果并继续处理,但不能忍受3分钟的延迟。
PS:此函数在内部使用JMS向另一个系统发送更新,并等待该系统响应并发送远离其他一些计算。
答案 0 :(得分:3)
你能否建议我在这个函数周围写一个包装器,这样如果函数没有用x ms / secs完成处理就会抛出一个中断的异常。
这是不可能的。 InterruptException
只会被特定方法抛出。你当然可以打电话给thread.stop()
但这已被弃用,不建议出于多种原因。
更好的选择是让您的代码在一段时间内等待响应,如果不起作用则放弃通话。例如,您可以将Callable
提交给实际调用"第三方内部库"的线程池。然后你的主代码将执行具有特定超时的future.get(...)
。
// allows 5 JMS calls concurrently, change as necessary or used newCachedThreadPool()
ExecutorService threadPool = Executors.newFixedThreadPool(5);
...
// submit the call to be made in the background by thread-pool
Future<Response> future = threadPool.submit(new Callable<Response>() {
public Response call() {
// this damn call can take 3 to 3000ms to complete dammit
return thirdPartyInternalLibrary.makeJmsRequest();
}
});
// wait for some max amount of time
Response response = null;
try {
response = future.get(TimeUnit.MILLISECONDS, 100);
} catch (TimeoutException te) {
// log that it timed out and continue or throw an exception
}
这种方法的问题在于,您可能会产生一大堆线程,等待库响应您无法控制的远程JMS查询。
没有简单的解决方案。
答案 1 :(得分:0)
由于这是第三方,您无法修改代码。因此,您需要做两件事
一种可能的方法是使用信号量。
final Semaphore semaphore = new Semaphore(0);
Thread t = new Thread(new Runnable() {
@Override
public void run() {
// do work
semaphore.release();
}
});
t.run();
try {
semaphore.tryAcquire(1, TimeUnit.SECONDS); // Whatever your timeout is
} catch (InterruptedException e) {
// handle cleanup
}
上面的方法很粗略,我建议改为使用专用工作队列或RxJava,如果可能的话,使用超时。
答案 2 :(得分:0)
如果lambda在分配的时间内没有完成,则会抛出TimeoutException
:
CompletableFuture.supplyAsync(() -> yourCall()).get(1, TimeUnit.SECONDS)