1

我有一个线程池(执行程序),我想监控它是否有过多的资源使用(因为 cpu 和内存似乎更难了)。我想“杀死”运行时间过长的线程,比如杀死一个操作系统进程。工作人员将大部分时间用于计算,但也有大量时间用于等待 I/O,主要是数据库......

我一直在阅读有关停止 java 中的线程以及由于资源清理原因(未正确释放锁、关闭套接字和文件等)而弃用它的内容。推荐的方法是定期检查工作线程是否应该停止然后退出。这显然期望客户端线程以某些方式编写,并且它们不会被阻塞等待某些外部 I/O。还有 ThreadDeth 和 InterruptedException 可能能够完成这项工作,但它们实际上可能在不正确/恶意编写的工作线程中被规避,而且我也有一个印象(虽然还没有测试)它们 InterruptedException 在某些(甚至所有)工作线程等待 I/O 的情况。

另一种缓解它的方法是使用多个操作系统进程来隔离系统的某些部分,但这会带来一些不必要的资源消耗增加。

这让我想起了五年多前关于隔离和/或 MVM 的老故事,但在这方面似乎没有发生任何事情,可能在 java 8 或 9 中......

所以,实际上,这一切让我想知道是否可以通过使用每个都有自己的类加载器的线程来实现一些糟糕的进程模拟?如果每个线程(或组)都将加载到自己的类加载器中,那是否可以用来模拟进程?我不确定这会带来多少资源消耗(因为不会有太多的代码共享并且代码也不小)。至少进程写时复制语义支持代码共享。

有什么建议/想法吗?

编辑:

我问是因为普遍的兴趣和失望,迄今为止在 JVM 中没有解决方案(我的意思是共享应用程序服务器实际上是不可能的 - .NET 中的应用程序域或类似的东西似乎正好解决了这种问题的问题)。我知道杀死一个进程并不能保证将所有系统状态恢复到某个初始状态,但至少释放所有资源,如句柄、内存和 cpu。我正在考虑使用类加载器,因为它们可能帮助释放线程持有的锁,这是不推荐使用 Thread.stop 的原因之一。在我目前的情况下,唯一应该释放的另一件事(我目前能想到的)是数据库连接,如果需要,可以单独/外部(由看门狗线程)处理。虽然,真的,在我的情况下 Thread.stop 可能实际上可行,我只是不喜欢使用不推荐使用的方法..

此外,我正在考虑将其作为行为不端过程的安全网,理想情况下它们应该表现良好,并且在我的控制下处于相当高的水平。

所以,为了澄清,我问的是服务器端的java人员如何处理失控的线程?我怀疑通过使用集群中的许多机器来解决问题并重新启动行为不端的机器 - 至少当应用程序是无状态的时......

4

1 回答 1

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");
    }
}
于 2012-03-18T21:30:04.963 回答