一尘不染

如何使外部方法可中断?

java

问题

我正在通过ExecutorService运行某些外部方法的多次调用。我希望能够中断这些方法,但是不幸的是,它们不能自行检查中断标志。有什么办法可以强制从这些方法引发异常?

我知道从任意位置抛出异常是潜在的危险,在我的具体情况下,我愿意抓住这次机会并准备处理后果。

细节

“外部方法”是指某些来自外部库的方法,并且我无法修改其代码(可以,但是,每当发布新版本时,这都会成为维护的噩梦)。

外部方法计算量大,不受IO限制,因此它们不响应常规中断,因此无法强制关闭通道或套接字等。如前所述,它们也不检查中断标志。

代码在概念上类似于:

// my code
public void myMethod() {
    Object o = externalMethod(x);
}

// External code
public class ExternalLibrary {
    public Object externalMethod(Object) {
        innerMethod1();
        innerMethod1();
        innerMethod1();
    }

    private void innerMethod1() {
        innerMethod2();
        // computationally intensive operations
    }

    private void innerMethod2() {
        // computationally intensive operations
    }
}

我尝试过的

Thread.stop()理论上将执行我想要的操作,但不仅不赞成使用它,而且还仅适用于实际线程,而我正在使用执行程序任务(例如,在线程池中工作时,它们也可能与将来的任务共享线程)
。不过,如果找不到更好的解决方案,我将把代码转换为使用老式线程,然后使用此方法。

我尝试过的另一种选择是myMethod()使用特殊的“
Interruptable”注释标记和类似的方法,然后使用AspectJ(我承认是新手)来捕获那里的所有方法调用-类似于:

@Before("call(* *.*(..)) && withincode(@Interruptable * *.*(..))")
public void checkInterrupt(JoinPoint thisJoinPoint) {
    if (Thread.interrupted()) throw new ForcefulInterruption();
}

但是withincode它并不递归到匹配方法所调用的方法,因此我将不得不将此注释编辑到外部代码中。


阅读 212

收藏
2020-12-03

共1个答案

一尘不染

我已经解决了我的问题的丑陋解决方案。它不是很漂亮,但是可以在我的情况下使用,因此我将其发布在这里,以防它对其他人有帮助。

我所做的是 分析
应用程序的库部分,希望我可以隔离一小部分被重复调用的方法,例如某些get方法equals()或类似的东西;然后我可以在其中插入以下代码段:

if (Thread.interrupted()) {
    // Not really necessary, but could help if the library does check it itself in some other place:
    Thread.currentThread().interrupt();
    // Wrapping the checked InterruptedException because the signature doesn't declare it:
    throw new RuntimeException(new InterruptedException());
}

通过编辑库的代码手动插入它,或者通过编写适当的方面自动插入它。请注意,如果库尝试捕获并吞下一个RuntimeException,则抛出的异常可以替换为库未尝试捕获的其他内容。

幸运的是,使用的VisualVM,我能找到一个 单一
的具体用法我正在图书馆的过程中调用了非常高数十倍方法。添加以上代码段后,它现在可以正确响应中断。

这当然是不可维护的,再加上什么也不能保证库在其他情况下会重复调用此方法。但这对我有用,并且由于配置其他应用程序并在其中插入检查相对容易,因此我认为这是一个通用的解决方案,尽管很难看。

2020-12-03