java - java中模拟OS进程/抢占式线程停止/classloader+线程进程模拟

标签 java multithreading process classloader preemptive

我有一个线程池(执行器),我想监视它是否过度使用资源(因为CPU和内存的时间似乎相当困难)。我想“杀死”运行时间过长的线程,例如杀死操作系统进程。工作人员大部分时间都花在计算上,但也花费了大量时间等待 I/O,主要是数据库......

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

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

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

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

有什么建议/想法吗?

编辑:

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

此外,我还将其视为行为不当流程的安全网,理想情况下,它们应该表现良好,并且在很大程度上处于我的控制之下。

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

最佳答案

线程和进程之间的区别在于线程隐式共享内存和资源,例如套接字和文件(使线程本地内存成为一种解决方法)。进程隐式拥有私有(private)内存和资源。

杀死线程不是问题。问题在于,行为不良的线程甚至行为合理的线程都可能使资源处于不一致的状态。使用类加载器不会帮助您跟踪此问题,也不会为您解决问题。对于进程来说,更容易跟踪它们正在使用哪些资源,因为大多数资源都是隔离的。即使对于进程来说,如果被杀死,它们也可能使锁、临时文件和共享 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");
    }
}

关于java - java中模拟OS进程/抢占式线程停止/classloader+线程进程模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9762194/

相关文章:

java - 使用访问权限和私钥访问google云存储java

java - 了解 Jetty 的内存使用情况

用于同时处理多个请求的 SOAP 服务器的 Python 库?

c++ - _beginthreadex 无法从 'overloaded-function' 转换

linux - ps h -fwC 有什么作用?

java - 使用 Java 杀死进程

java - Bluemix 中的流分析服务出错

Java 9 ifPresentOrElse 返回值

multithreading - 这里需要 volatile 吗?

c - Waitpid 被系统调用中断