如何在Java中中断函数调用

如何在Java中中断函数调用,java,multithreading,Java,Multithreading,我正在尝试使用正在处理给定请求的第三方内部库。不幸的是,它本质上是同步的。同样的,我也无法控制代码。基本上它是一个函数调用。此函数的行为似乎有点不稳定。有时此功能需要10毫秒才能完成处理,有时需要300秒才能处理请求 你能给我建议一种方法,在这个函数周围写一个包装器,这样如果函数不能以x毫秒/秒的速度完成处理,它就会抛出一个中断的异常。我可以忍受没有结果并继续处理,但不能容忍3分钟的延迟 PS:该函数使用JMS在内部向另一个系统发送更新,并等待该系统响应并发送一些其他计算 你能给我建议一种方法,

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

你能给我建议一种方法,在这个函数周围写一个包装器,这样如果函数不能以x毫秒/秒的速度完成处理,它就会抛出一个中断的异常。我可以忍受没有结果并继续处理,但不能容忍3分钟的延迟

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

你能给我建议一种方法,在这个函数周围写一个包装器,这样如果函数不能以x毫秒/秒的速度完成处理,它就会抛出一个中断的异常

这是不可能的<代码>中断异常仅由特定方法引发。您当然可以调用
thread.stop()
,但这是不推荐使用的,并且不推荐使用,原因有很多

更好的替代方法是让代码等待响应一段时间,如果不起作用,就放弃调用。例如,您可以向实际调用“第三方内部库”的线程池提交一个
可调用的
。然后您的主代码将执行一个
未来。使用特定的超时获取(…)

// 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
}
//允许同时进行5次JMS调用,根据需要进行更改或使用newCachedThreadPool()
ExecutorService线程池=Executors.newFixedThreadPool(5);
...
//通过线程池提交要在后台进行的调用
Future=threadPool.submit(new Callable()){
公众回应电话(){
//这个该死的电话可能需要3到3000毫秒才能完成
返回第三方InternalLibrary.makeJmsRequest();
}
});
//等待最长的时间
响应=空;
试一试{
response=future.get(TimeUnit.millizes,100);
}捕获(TimeoutException te){
//记录它超时并继续或引发异常
}
这种方法的问题是,您可能会产生一大堆线程,等待库响应远程JMS查询,而您对此没有太多控制权


没有简单的解决方案。

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

  • 在新线程中启动执行
  • 在当前线程中等待执行,超时 一种可能的方法是使用信号量

        final Semaphore semaphore = new Semaphore(0);
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                // do work
                semaphore.release();
            }
        });
    
        t.start();
        try {
            semaphore.tryAcquire(1, TimeUnit.SECONDS); // Whatever your timeout is
        } catch (InterruptedException e) {
            // handle cleanup
        }
    

    上面的方法很糟糕,我建议您更新您的设计,如果可能的话,使用一个专用的工作队列或带有超时的RxJava

    如果lambda没有在分配的时间内完成,这将抛出一个
    TimeoutException

    CompletableFuture.supplyAsync(() -> yourCall()).get(1, TimeUnit.SECONDS)
    

    使用线程调用该方法,并在x时间后杀死该线程?他说这是同步的。。。不会那么容易的。。。如果库本身不支持超时,您需要修改它的代码。查看Executors接口,在单独的线程中启动您的函数,并使用一些时间限制方法,如等待终止。这里有更多的内容:你不能把它扔到一个线程中,然后启动一个计时器,在一段时间后杀死线程,或者在调用超过计时器时停止响应吗?谢谢。我刚试过这个,这个似乎很管用。不幸的是,我们目前正在使用Java1.7,因此可能无法充分利用这些特性。谢谢你的回答。另一个推动我们的应用程序使用Java 1.8的原因。另外,我不能投票,因为我是StackOverflow新手,没有这样做的特权。