Process.waitFor() 死鎖問題了解和解決


 

ProcessBuilder pb = new ProcessBuilder("C:\\Debug\\TestRedis.exe", keyNmae);
pb.redirectErrorStream(true);
Process process = pb.start();
//可能導致進程阻塞,甚至死鎖
int ret = process.waitFor();

 

1、waitFor問題描述分析

1、 主進程中調用pb.start會創建一個子進程,用於執行shell /exe 腳本。子進程創建后會和主進程分別獨立運行。
2.、因為主進程需要等待腳本執行完成,然后對腳本返回值或輸出進行處理,所以這里主進程調用process.waitFor()等待子進程完成。

3.、進程執行過程就是不斷的打印信息。主進程中可以通過Process.getInputStream和Process.getErrorStream獲取並處理。
4.、這時候子進程不斷向主進程發生數據,而主進程調用Process.waitfor后已掛起。當前子進程和主進程之間的緩沖區塞滿后進程不能繼續寫數據,然后也會掛起
5.、這樣子進程等待主進程讀取數據,主進程等待子進程結束,兩個進程相互等待,最終導致死鎖。

 

2、解決死鎖問題

基於上述分析,只要主進程在waitFor之前,能不斷處理緩沖區中的數據就可以。因為,我們可以再waitfor之前,單獨啟2個額外的線程,分別用於處理InputStream和ErrorStream就可以

                try (
                        InputStream inputStream = process.getInputStream();
                        InputStream inputErrorStream = process.getErrorStream();
                ) {
                    // 讀取Shell的輸出內容,並添加到string中:
                    //啟動兩個線程,一個線程負責讀標准輸出流,另一個負責讀標准錯誤流
                    new Thread(() -> {
                        try {
                            val msg = IOUtils.toString(inputStream, StandardCharsets.UTF_8);
                            response.setShellOutput(msg);
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                        }
                    }).start();

                    new Thread(() -> {
                        try {
                            var errMsg = IOUtils.toString(inputErrorStream, StandardCharsets.UTF_8);
                            response.setShellErrorOutput(errMsg);
                        } catch (Exception e) {
                            log.error(e.getMessage(), e);
                        }
                    }).start();

                    process.waitFor(2, TimeUnit.HOURS);////可能導致進程阻塞,甚至死鎖
                    int exitCode = process.exitValue();//
                    response.setSuccessful(exitCode == SHELL_EXIT_CODE_SUCCESS);
                }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM