如何在Java中断函数调用

时间:2016-05-24 18:53:15

标签: java multithreading

我正在尝试使用正在处理给定请求的第三方内部库。不幸的是,它本质上是同步的。此外,我无法控制相同的代码。基本上它是一个函数调用。这个功能在行为上似乎有些不稳定。有时此功能需要10毫秒才能完成处理,有时需要300秒来处理请求。

你能否建议我在这个函数周围编写一个包装器,这样如果函数没有用x ms / secs完成处理,就会抛出一个中断的异常。我可以忍受没有结果并继续处理,但不能忍受3分钟的延迟。

PS:此函数在内部使用JMS向另一个系统发送更新,并等待该系统响应并发送远离其他一些计算。

3 个答案:

答案 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)

由于这是第三方,您无法修改代码。因此,您需要做两件事

  1. 在新主题中启动执行。
  2. 等待在当前线程中执行,超时。
  3. 一种可能的方法是使用信号量。

        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)