我有一个线程池(执行器),我想监视过多的资源使用情况(因为cpu和内存似乎相当困难)。我想'杀死'运行时间太长的线程,比如杀死操作系统进程。工作人员花费大部分时间进行计算,但是等待I / O的时间也很长,主要是数据库......
我一直在阅读在java中停止线程以及如何因资源清理原因而弃用它(不正确地释放锁,关闭套接字和文件等)。建议的方法是定期检查工作线程是否应该停止然后退出。这显然期望客户端线程以某种方式写入,并且它们不会被阻塞等待某些外部I / O.还有ThreadDeth和InterruptedException可以完成这项工作,但它们实际上可以在不正确/恶意编写的工作线程中被绕过,而且我得到了一个印象(虽然还没有测试),他们的InterruptedException可能在某些方面无法正常工作(当工作线程等待I / O时,甚至所有情况。
缓解它的另一种方法是使用多个操作系统进程来隔离系统的某些部分,但它会带来一些不必要的资源消耗增加。
这让我想起了五年前关于隔离和/或MVM的那个古老故事,但似乎没有发生过这方面的事情,可能是在java 8或9 ......
所以,实际上,这一切都让我徘徊是否可以通过使用每个都拥有自己的类加载器的线程来实现一些可怜的进程模拟?如果每个线程(或组)都会加载到自己的类加载器中,那可以用来模拟进程吗?我不确定会带来多少资源消耗(因为代码共享不多,代码也不小)。至少进程写时复制语义启用代码共享..
任何建议/想法?
编辑:
我问,因为一般的兴趣和一种失望,到目前为止JVM中还没有解决方案(我的意思是共享应用程序服务器实际上不可能 - 应用程序域,或类似的东西,在.NET中似乎要解决正是这种问题)。我知道杀死进程并不能保证将所有系统状态恢复到某些初始状态,但至少会释放所有resorces,如句柄,内存和cpu。我正在考虑使用类加载器,因为它们可能帮助释放线程持有的锁,这是不推荐使用Thread.stop的原因之一。在我目前的情况下,唯一应该发布的东西(我现在可以想到)是数据库连接,如果需要,可以单独/外部(通过看门狗线程)处理。 虽然,实际上,在我的情况下,Thread.stop实际上可能是可行的,但我不喜欢使用弃用的方法。
此外,我认为这是行为不端过程的安全网,理想情况下,他们应该表现得很好,并且在我的控制下处于相当高的程度。
所以,为了澄清,我问如何在服务器端的java人处理失控线程?我怀疑通过使用群集中的许多机器来抵消问题并重新启动行为不端的问题 - 当应用程序至少是无状态时......
答案 0 :(得分:1)
线程和进程之间的区别在于线程隐式共享内存和资源(如套接字和文件)(使线程本地内存成为一种解决方法)。进程隐式拥有私有内存和资源。
杀死线程不是问题。问题是行为不良的线程甚至是合理的行为线程都会使资源处于不一致状态。使用类加载器无法帮助您跟踪此问题,也无法为您解决问题。对于流程,它更容易跟踪他们正在使用的资源,因为大多数资源都是隔离的。即使对于进程,如果被杀死,它们也会使锁,临时文件和共享IPC资源处于不正确的状态。
真正的解决方案是编写行为正常的代码,以便可以对其进行管理和解决,并且尝试处理每个可能性能不佳的代码几乎是不可能的。如果你有一个坏的第三方库你必须使用,你可以尝试杀死和清理它,你可以提出一个好的解决方案,但你不能指望它是一个干净的。
public static void main(String... args) throws IOException {
switch(args.length) {
case 1: {
// server
ServerSocket ss = new ServerSocket(Integer.parseInt(args[0]));
Socket s = ss.accept();
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
// will deadlock before it gets here
break;
}
case 2: {
Socket s = new Socket(args[0], Integer.parseInt(args[1]));
ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
// will deadlock before it gets here
break;
}
default:
System.err.println("Must provide either a port as server or hostname port as client");
}
}