Java库维护进程池

10

我正在开发一个需要并发处理的Java守护进程:一个无限循环监听作业队列 (redis) 并将每个作业分配给一个工作者(worker)。这个工作者不一定需要返回一个值。

我发现 Executors (线程池) 非常有用,目前我正在使用ThreadPoolExecutor来维护一定数量的工作者线程。

然而,这些工作者运行第三方代码,需要尽可能隔离, 避免共享静态属性。

我的问题是:是否有任何类似于Executors的Java库/框架,提供类似以下功能:

  • 工作者池(worker pools)
  • 自动调整池大小

..但是使用进程(processes)代替线程?

3个回答

8
我了解您有第三方库需要以某种方式进行隔离运行,以便它们无法访问静态变量等内容。我建议在另一个ClassLoader中运行您的任务。有些Web框架使用此机制来隔离Web请求。在类加载器之间传递数据有点棘手。我不确定Jetty是如何做到的。也许使用某种套接字?这里有一篇关于使用System.out共享对象的有趣文章。当然,这是一种hack方法。
我的问题是:是否有任何类似于Executors的Java库/框架,它可以生成进程而不是线程?
现代操作系统将利用现代多处理器体系结构,以获得Java线程的最佳效果。在当前进程内生成另一个线程将在另一个可用的处理器上运行,并且比在完全独立的进程中运行该任务(特别是像另一个JVM进程这样重的任务)要高效得多。

谢谢您的回答@Gray,我理解您的观点。但在这种情况下,我需要将这些工作进程隔离开来(例如,防止共享静态变量等),并且可能在具有不同系统属性的JVM中运行它们。因此,我的问题仍然存在,如果我需要运行多个进程(而不是线程),是否有框架可以帮助? 另外,请再次查看此问题的标题,因为我真正询问的是是否存在这样的框架,而不是是否明智使用它。 - dimi
你可以在另一个类加载器中运行它们。这就是Web服务器用来隔离类的方法。我不确定如何在两个类加载器之间传递数据。也许可以使用某种套接字:http://www.devx.com/java/Article/31614/1954 - Gray
@MartinJames 我同意,但是我完全没有权限访问那部分代码。 - dimi
我不知道有这样的框架,@dbalaouras。 我认为我的答案仍然适用。 - Gray
当然,@Gray,我正在查看你的建议。但是我指的是我的问题标题。除非您不介意我更新它。 - dimi
显示剩余8条评论

2

有一个在 GitHub 上创建进程池的项目,请查看:https://github.com/shri30/ProcessPool

这里是一个示例:

示例代码:

public class UsageExample implements JTask{


    public static void main(String args[]) throws Exception{
        //Create a pool with name : UsageExample-Process and number of processes : 3
        ExecutorService pool = ProcessPool.createProcessPool("UsageExample-Process", 3);
        ProcessFuture<TaskStatus> pf1 = pool.submit(Task.class, args);
        ProcessFuture<TaskStatus> pf2 =pool.submit(Task.class, args);
        ProcessFuture<TaskStatus> pf3 =pool.submit(Task.class, args);
        ProcessFuture<TaskStatus> pf4 =pool.submit(Task.class, args);
        ProcessFuture<TaskStatus> pf5 =pool.submit(Task.class, args);
        //the get method blocks the call to get the result
        TaskStatus ts= pf1.get();
        Status status = ts.getStatus();
        if(status == Status.SUCESS){
        //code goes here
        }

        TaskStatus ts2= pf2.get();
        Status status2 = ts.getStatus();
        if(status == Status.SUCESS){
        //code goes here
        }


        TaskStatus ts3= pf3.get();
        Status status3 = ts.getStatus();
        if(status == Status.SUCESS){
        //code goes here
        }


        TaskStatus ts4= pf4.get();
        Status status4 = ts.getStatus();
        if(status == Status.SUCESS){
        //code goes here
        }
        //terminate the pool - pass true for graceful termination, the second parameter is minutes
        //wait for task completion
        pool.terminate(true, 3000);
    }


}

class Task implements JTask{

    public static void main(String[] args) {
        System.out.println("Executing the sample task");
    }

}

请详细阐述一个实际的答案,不要只发布外部链接。 - abarisone
我继续为你详细说明了。 - Nicholas DiPiazza

1
你有没有考虑过使用ProcessBuilder来管理你的隔离进程?
String myJar = MyClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
ProcessBuilder pb = new ProcessBuilder("java", "-classpath", myJar, "package.MainClass");
Process p = pb.start();

我不确定将管理子进程的Runnable任务提交给Executor是否是一个好主意,但这可能是隔离工作线程的解决方案。


嗯...刚看到这个..有趣的想法。我需要检查它是否可行,但也要注意你提到的Executor的任何影响。谢谢! - dimi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接