鉴于该库的使用存在内存泄漏这一事实,我想忽略从线程到进程的实现,我将能够在启动后的指定时间后关闭并重新打开该进程。
我的实现:
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中的进程仍然存在并且他的内存正在增长。
答案 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上的自定义协议。
最后,您应该控制子进程,不要忘记终止它。为了避免在父进程意外死亡的情况下,您可以在子进程中启动线程,以检查父进程是否仍然存在。