我有一个系统,当它收到来自webservice的调用时启动workers。Worker由ExecutorService启动,要启动的类实现Runnable。但是,如果工作线程超时,我将无法实际杀死该工作线程,这将导致我的系统出现资源问题。
public class MyClass implements Runnable {
public void internalCall() {
logger.info("B-1");
//Some business code which may take too long
// <...>
logger.info("B-2");
}
public void launch() {
// Wrapper
Callable<Object> callable = new Callable<Object>() {
@Override
public Object call() throws Exception {
internalCall();
return null;
}
};
// Submit
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Object> future = executor.submit(callable);
try {
// Wait
future.get(1, TimeUnit.SECONDS);
}
catch (TimeoutException e) {
logger.warn("Timeout");
}
finally {
logger.info("A-1");
executor.shutdownNow();
future.cancel(true);
logger.info("A-2");
}
}
}
如果工作线程超时,我将看到以下日志消息:
INFO | B-1
WARN | Timeout
INFO | A-1
INFO | A-2
然后是保持空闲的服务,直到另一个工作者请求进入。然而,尽管对ExecutorService和Future分别调用了shutdownNow()和cancel(),worker仍继续:
INFO | B-1
WARN | Timeout
INFO | A-1
INFO | A-2
INFO | B-2
我环顾四周,发现还有许多关于杀死线程的类似问题,普遍的共识是不应该这样做。然而,这是一个可以扩展的类,其目的是重写internalCall()——这意味着我不能依赖internalCall来监控自身和检查线程。isInterrupted()或类似的内容。
我只想通过攻击furure或executor对象来强制从launch()方法杀死东西。
首先,未来。取消(true)不会终止正在运行的线程。它只是试图以“礼貌的方式”停止处决。
它的作用是或多或少地发送中断信号,就像您在代码中某处调用yourthread.interrupt()
一样。
只有当run()方法中的代码检查中断时,它才会停止处理。因此,在您的internalCall()
中,您需要不时检查线程是否未被调用线程中断。中断()并停止执行。中断还将通过抛出InterruptedExceptan停止sleep()、wait()、IO操作(这就是为什么这些方法会抛出这样的异常)。
ExecutorService使用相同的机制,因此它将尝试中断正在运行的线程,但同样,如果代码未检查此类中断,线程将继续运行。
由于各种原因,不应简单地终止线程(检查java文档中的thread.stop()方法以及为什么不推荐该方法),通知线程可能应该停止工作的“通用”方法是中断信号。
N、 B。
如果线程不响应Thread.interrupt?
在某些情况下,可以使用特定于应用程序的技巧。例如,如果一个线程正在等待一个已知的套接字,则可以关闭该套接字以使线程立即返回。不幸的是,实际上没有任何技术可以在一般情况下起作用。应该注意的是,在等待线程不响应线程的所有情况下。中断,它不会响应线程。停止任何一个。此类情况包括蓄意拒绝服务攻击,以及针对哪个线程的I/O操作。停止并穿线。中断无法正常工作。-Java线程原语弃用
那么我们学到了什么。。。在Java中,不要运行第三方代码,因为这些代码与主应用程序的执行是不可信任的。即使是Thread。stop do work你还有一大堆比不检查中断状态的线程糟糕得多的事情(即代码html" target="_blank">调用系统。退出(0))。
我建议您对不信任的第三方代码执行以下操作之一:
>
将第三方代码作为由您控制其执行的Java运行的评估语言运行。一些示例是:Drools等规则语言或JMustache等无逻辑模板语言。
在单独的执行中运行第三方代码,并使用您的操作系统终止进程和IPC,如用于通信的套接字。
问题内容: 如何java.lang.Thread用Java 杀死A ? 问题答案: 有关他们为何不赞成使用Sun的内容,请参见此主题。它详细介绍了为什么这是一种不好的方法,以及通常应该采取什么措施才能安全地停止线程。 他们建议的方式是使用共享变量作为标志,要求后台线程停止。然后可以由另一个请求线程终止的对象来设置此变量。
我有一个工作正常的GUI类,但是我在那个GUI类中有一个按钮,应该是从另一个类打开一个新的GUI... 然而,当调用新的GUI类(newGui)时,它只是一个透明窗口。这是因为两个GUI不能同时运行吗? 我现在正试图以线程的形式打开新的GUI,但我不知道该怎么做! 公开无效运行(); 这是我的尝试,但不出所料,这没有成功。 有什么帮助吗? 谢谢
我正在尝试运行这个简单的类,并且对于每个cicle,我正在计算java进程线程的数量。 ps huH p pid wc-l。 对于每个cicle,线程数是availableProcessors()数的增加。 当ExecutorService在其他线程中运行时,garbace收集器似乎不会释放僵尸线程。 如果我创建了一个静态ExecutorService,它就不会发生
问题内容: 我有一个简单的程序,可以测试当模块不存在时是否能够引发异常。 有时我喜欢在另一个模块中使用此代码: 令人惊讶的是,当我以这种方式运行它时,它不起作用: 这种情况在Ubuntu中发生,并且在干净的CentOS 7.3中也发生。 问题答案: 您正在遇到“导入锁定”。 该文档提到了线程期间导入的限制,您违反了第一个限制(强调我的意思): 虽然导入机制是线程安全的,但是由于提供线程安全的方式存
问题内容: 我有一个程序’foo’运行不同的线程,fooT1,fooT2,.. fooTn。 现在,如果我想编写另一个程序“ bar”,它可能会杀死线程fooTr,那可能吗? 原因:fooTr线程之一跟踪产品许可证。如果该线程被杀死;可能会无限期地运行此产品。杀死’foo’本身可以容忍为’foo’,因为这正是许可证到期时所做的事情。 系统:Linux的Fedora发行 注:用于启动JVM和程序fo
问题内容: 我正在使用命令在UNIX中查看JVM的线程转储。但是在哪里可以找到此命令的输出?我搞不清楚了!! 问题答案: 您也可以使用jstack(JDK附带)进行线程转储并将输出写入所需的任何位置。在Unix环境中不可用吗?