将线程更改为Java处理

时间:2018-07-10 12:03:08

标签: java multithreading memory-leaks process

鉴于该库的使用存在内存泄漏这一事实,我想忽略从线程到进程的实现,我将能够在启动后的指定时间后关闭并重新打开该进程。

我的实现:

public class MyClass {

private MyClassAgent myClassAgent ;

private Thread mainThread;
private final AtomicBoolean running = new AtomicBoolean(false);

static {
    Webcam.setDriver(new MyCompositeDriver());
}

public static void main(String[] args) {
    new MyClass().init("192.168.1.91", 2000, 0, 25);
    new MyClass().init("192.168.1.91", 2001, 10, 25);
}

    ...

public void init(String host, int port, int camera, Dimension dimension, int fps) {
    try {
        running.set(true);
        mainThread = new Thread(() -> {
            while (running.get()) {
                List<Webcam> webcamList = new ArrayList<Webcam>();
                for (Webcam webcam : Webcam.getWebcams())
                    if (!webcam.getName().contains("IP"))
                        webcamList.add(webcam);

                if (webcamList.size() > camera) {
                    Webcam webcam = webcamList.get(camera);
                    if (webcam.getLock().isLocked())
                        webcam.getLock().disable();
                    webcam.setViewSize(dimension);
                    webcam.open(true);

                    myClassAgent = new StreamingClientAgent(webcam, dimension, fps);
                    myClassAgent.connect(new InetSocketAddress(host, port));
                } else {
                    logger.info("Podana kamera nie istnieje");
                }
            }
        });
        mainThread.run();
    } catch (Exception e) {
        logger.info("Blad w zwiazku z kamera : " + e.getMessage());
    }
}

public void stop() {
    myClassAgent.stop();
    running.set(false);
}
}

我该怎么做?我不能只关闭线程并重新打开,因为TaskManager中的进程仍然存在并且他的内存正在增长。

1 个答案:

答案 0 :(得分:0)

java平台为您启动一个外部进程提供了java.lang.ProcessBuilder

您必须使用参数指定命令,就像您从命令行启动Java应用程序一样。因此,命令为java,参数为<jvm params like Xmx> -cp <classpath> <mainclass> <program arguments>。要获取类路径,可以使用值System.getProperty("java.class.path")-这样,您创建的进程将在类路径中包含“父”应用程序所拥有的所有内容,因此您可以在项目中直接编写子应用程序的代码:

public Process start() throws InvocationTargetException, NoSuchMethodException, IllegalAccessException, NoSuchFieldException, IOException {
    final String cp = System.getProperty("java.class.path");
    final ProcessBuilder builder = new ProcessBuilder("java", "-cp", cp, com.example.ExternalProcessMain.class.getName());
    builder.redirectError(ProcessBuilder.Redirect.INHERIT); //in case of std communication
    builder.redirectOutput(ProcessBuilder.Redirect.INHERIT);  //in case of std communication
    return builder.start();  }

下一个要解决的问题是父子进程之间的通信。可以通过stdout或通过套接字来完成。如果您只需要从子进程到父进程流式传输二进制数据,那将很容易。如果您需要诸如方法调用之类的复杂通信,则必须实现一些更复杂的解决方案。可能是某些消息传递系统,REST API或套接字/ stdin-out上的自定义协议。

最后,您应该控制子进程,不要忘记终止它。为了避免在父进程意外死亡的情况下,您可以在子进程中启动线程,以检查父进程是否仍然存在。