如何中断未完成且未抛出ThreadInterruptionException的Java代码

如何中断未完成且未抛出ThreadInterruptionException的Java代码,java,multithreading,concurrency,Java,Multithreading,Concurrency,大量任务已提交到我的应用程序,但它一直挂起,我跟踪到以下代码: uk.ac.shef.wit.simmetrics.tokenisers.TokeniserWhitespace.tokenizeToArrayList(TokeniserWhitespace.java:133) uk.ac.shef.wit.simmetrics.similaritymetrics.CosineSimilarity.getSimilarity(CosineSimilarity.java:142) com.jthin

大量任务已提交到我的应用程序,但它一直挂起,我跟踪到以下代码:

uk.ac.shef.wit.simmetrics.tokenisers.TokeniserWhitespace.tokenizeToArrayList(TokeniserWhitespace.java:133)
uk.ac.shef.wit.simmetrics.similaritymetrics.CosineSimilarity.getSimilarity(CosineSimilarity.java:142)
com.jthink.songkong.match.Scorer.compareValues(Scorer.java:74)
com.jthink.songkong.match.Scorer.calculateTitle(Scorer.java:704)
com.jthink.songkong.match.Scorer.matchRecordingOrTrackTitle(Scorer.java:652)
com.jthink.songkong.match.Scorer.calculateTrackScoreWithinRelease(Scorer.java:538)
com.jthink.songkong.match.Scorer.scoreMatrix(Scorer.java:396)
com.jthink.songkong.match.Scorer.calculateReleaseScore(Scorer.java:1234)
它基本上是第三方库中的字符串匹配算法,但它不会抛出ThreadInterruptedException,所以这是否意味着我不能中断它,但肯定是一个长时间运行的过程,已经运行了30分钟。我有一个对监视此代码的线程的引用,但是是否有方法阻止它

当然,我希望修复第三方库,但与此同时,我需要一种方法来停止我的应用程序挂起取消这些挂起任务。更糟糕的是,我使用Hibernate,在这个堆栈中创建了一个Hibernate会话,因为这个TokeniserWhitespace方法永远不会完成我的会话(因此数据库连接)从未发布,因此最终我耗尽了数据库连接,应用程序完全挂起。

您可以使用库来包装有问题的代码-这将允许您在代码挂起时终止并重新启动代码

import scala.concurrent.Future;

public interface ProblemCode {
  public Future<String> stringMatch(String string);
}

public class ProblemCodeImpl implements ProblemCode {
  public Future<String> stringMatch(String string) {
    // implementation
  }
}
导入scala.concurrent.Future;
公共接口问题代码{
公共未来字符串匹配(字符串);
}
公共类ProblemCodeImpl实现ProblemCode{
公共未来字符串匹配(字符串){
//实施
}
}

导入akka.actor.actor系统;
导入akka.actor.TypedActor;
导入scala.concurrent.Await;
导入scala.concurrent.duration.duration;
导入akka.actor.TypedProps;
公共类控制器{
私有最终ActorSystem系统=ActorSystem.create(“名称”);
私有ProblemCode problemCodeActor=getProblemCodeActor();
私有ProblemCode getProblemCodeActor(){
返回TypedActor.get(system.typedActorOf)(新的TypedProps(ProblemCode.class,problemcodepimpl.class));
}
公共字符串控制器字符串匹配(字符串字符串){
while(true){
试一试{
//等待将来返回字符串
返回wait.result(problemCodeActor.stringMatch(字符串),Duration.create(5000,TimeUnit.毫秒));
}捕获(超时异常e){
//等待超时,因此停止该演员并创建一个新演员
TypedActor.get(系统).stop(问题代码执行器);
problemCodeActor=getProblemCodeActor();
}
}
}
}
换句话说,控制器对已包装在actor中的问题代码调用
stringMatch
;如果超时(在我的示例中为5000毫秒),则停止并重新启动actor,然后再次通过controller方法进行循环


ProblemCode
一次只执行一个方法(它将使后续调用排队),因此如果您想同时执行
stringMatch
,您需要创建多个参与者,并用它们创建一个路由器/将它们放在队列中/等等。

我会尝试
Thread.interrupt()
即使未引发中断的异常,也不一定意味着第三方库无法以其他方式正确处理它。如果这不起作用,那么我会考虑<代码>线程>()(代码)>尽管它被破坏了,希望库的设计能够处理突然终止,并且不会以不一致的状态结束(由于使用它的事务性质,我怀疑有许多共享对象会被破坏)。代码>线程。停止()将导致事件立即停止,并抛出一个
线程死亡
异常,无论它在做什么,它都被Sun弃用,因为它可能会使共享对象处于未知和不一致的状态。

如果您中断它会发生什么?我不能尝试它,因为它只发生在客户身上,但我假设什么都不会发生?至少有一个战斗的机会,你会得到一些例外回来。中断被广泛地错误处理,它们被包装在RuntimeException中并重新启动并不罕见。如果被中断的线程没有主动检查isInterrupted()标志,我仍然不清楚中断线程是否有任何影响。这个问题的标准答案如下:在代码的配合下,您可以使用它支持的任何方法中断它。如果没有代码的配合,任何中断代码的方法都不能保证安全。但是,将代码隔离到自己的进程通常可以安全地终止进程上下文,只要代码不在其进程上下文之外操作敏感资源“可以包括共享内存、服务器进程、物理对象、网络连接等。您似乎在声称此库完成了可证明不可能的任务。”。如果问题代码在您尝试停止时破坏了流程级别不变,会发生什么情况?如果一个库不知道它正在停止的代码的内部结构,它怎么能恢复该不变量呢?例如,假设该库是这样工作的:
1)如果正在进行的任务太多,请稍候。2) 增加正在进行的任务数。3) 干活儿。4) 减少正在进行的任务数。
在第三步中中断任务将导致正在进行的任务数无限增加,最终导致所有任务永远等待。如果没有实现该任务的代码的配合,就不能中断该任务。如果代码控制了一个物理对象,并且正在做类似于驾驶或烹饪的事情,该怎么办?@DavidSchwartz在这种情况下,其目的是杀死并重新启动库也会重新启动任务计数。如果任务计数是一个共享可变变量,那么Akka不是一个合适的库来使用(除非该共享可变变量可以放在一个也可以重新启动的父参与者中),使用我提供的代码片段,我们不可能创建这样一个共享的可变变量——我的意图是,如果他对Akka有足够的兴趣的话
import akka.actor.ActorSystem;
import akka.actor.TypedActor;
import scala.concurrent.Await;
import scala.concurrent.duration.Duration;
import akka.actor.TypedProps;

public class Controller {

  private final ActorSystem system = ActorSystem.create("Name");

  private ProblemCode problemCodeActor = getProblemCodeActor();

  private ProblemCode getProblemCodeActor() {
    return TypedActor.get(system).typedActorOf(new TypedProps<ProblemCodeImpl>(ProblemCode.class, ProblemCodeImpl.class));
  }

  public String controllerStringMatch(String string) {
    while(true) {
      try {
        // wait for a Future to return a String
        return Await.result(problemCodeActor.stringMatch(string), Duration.create(5000, TimeUnit.MILLISECONDS));
      } catch (TimeoutException e) {
        // Await timed out, so stop the actor and create a new one
        TypedActor.get(system).stop(problemCodeActor);
        problemCodeActor = getProblemCodeActor();
      }
    }
  }
}