日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java采用Process.destroy无法停止子进程

發布時間:2024/3/13 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java采用Process.destroy无法停止子进程 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

問題描述

當前的應用場景是,采用java執行一個python腳本,該腳本是一個機器學習算法,在訓練中會比較耗時。在某些場景下,需要采用java的進程主動停止該python進程。采用如下思路進行該邏輯實現。

一種錯誤的實現

啟動進程

ProcessBuilder builder = new ProcessBuilder("/bin/sh", "-c", command);TaskExecutor executor = privpyClient.getTaskExecutor(requestId);builder.redirectErrorStream(true);log.info("{} enter running the code: {}", requestId, command);Process process = null;try {process = builder.start();if (Objects.nonNull(executor)) {executor.setPlainProcess(process);}log.info("{} check if the code is started {}!", requestId, process.isAlive());} catch (IOException e) {log.error("{} start the process {} failed!,error:{}", requestId, command, e);return false;}

其中command就是“python3 test.py”的啟動python進程的語句。

停止進程

Field f = process.getClass().getDeclaredField("pid"); f.setAccessible(true); long pid = f.getLong(process) + 1; log.info("{} kill process pid {} start", requestId, pid); process.destroy();

這里不需看細節,其實就是將對應的process對象先進行了存儲,之后在主動停止時進行了一次調用。

其實其中的pid+1已經一定程度暴露了信息,因為我們發現真正的python進程號總是與process對象拿到的差1。

例如,我們從process拿到的pid為307,然python的進程號是308

效果


執行完process.destroy()后,對應的307進程退出,但是被拉起的308號python進程仍舊在系統中好好的存在。

問題思考

1、process作為java的進程抽象類,其真正作用是在java進程中再啟動一個子的java進程;這個停止動作也只能作用到這個主進程;
2、其中的python進程比啟動的子進程大1,因此可以從這個邏輯出發,在java停止掉process時,再發送一個系統調用的停止信號。

最后實現如下

public static void killPlainProcess(Process process, String requestId) throws Exception {Field f = process.getClass().getDeclaredField("pid");f.setAccessible(true);long pid = f.getLong(process) + 1;log.info("{} kill process pid {} start", requestId, pid);killChildProcess(pid);process.destroy();log.info("{} kill process pid {} finished ", requestId, pid); }/*** mind here, the process usd for call the kill should be clear too!!** @param pidNum*/ private static void killChildProcess(long pidNum) throws Exception {String cmd = "kill -15 " + pidNum;try {Process killProcess = null;killProcess = Runtime.getRuntime().exec(cmd);killProcess.waitFor();TimeUnit.MILLISECONDS.sleep(100);killProcess.destroy();} catch (IOException | InterruptedException e) {throw e;} }

注意點:在又啟動了一個process來執行kill -15信號后,需要注意將自己也執行killProcess.destroy();做好資源清理。
但是發現多次執行后,存在不穩定情況,會導致主進程掛掉。

正確拉起python進程的實現

#### 啟動進程 ProcessBuilder builder = new ProcessBuilder("Python", command); TaskExecutor executor = privpyClient.getTaskExecutor(requestId); builder.redirectErrorStream(true); log.info("{} enter running the code: {}", requestId, command); Process process = null; try {process = builder.start();if (Objects.nonNull(executor)) {executor.setPlainProcess(process);}log.info("{} check if the code is started {}!", requestId, process.isAlive()); } catch (IOException e) {log.error("{} start the process {} failed!,error:{}", requestId, command, e);return false; }

其中command就是“test.py”。

總結

以上是生活随笔為你收集整理的java采用Process.destroy无法停止子进程的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。