最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解決Java執(zhí)行Cmd命令出現(xiàn)的死鎖問題

 更新時間:2022年07月21日 10:19:58   作者:Stars-one  
這篇文章主要介紹了關于Java執(zhí)行Cmd命令出現(xiàn)的死鎖問題解決,解決方法就是在waitfor()方法之前讀出窗口的標準輸出、輸出、錯誤緩沖區(qū)中的內容,本文給大家介紹的非常詳細,需要的朋友可以參考下

問題

之前研究了Java通過執(zhí)行cmd命令從而觸發(fā)Android打包的思路,但是發(fā)現(xiàn)Android打包成功之后,后面的代碼邏輯就不走了(連輸出都沒有)

經過了一天的排查,終于是從網(wǎng)上找到了解決方法

原因及解決方法

原因分析: 在上面提及了, process創(chuàng)建的子進程沒有自己的控制臺或終端,其所有的io操作都是通過(輸入流、輸出流、錯誤流)重定向到父進程中

如果該可執(zhí)行程序的輸入、輸出或者錯誤輸出比較多的話,而由于運行窗口的標準輸入、輸出等緩沖區(qū)有大小的限制,則可能導致子進程阻塞,甚至產生死鎖

其解決方法就是在waitfor()方法之前讀出窗口的標準輸出、輸出、錯誤緩沖區(qū)中的內容。

方法封裝

下面代碼中的TeeInputStream是在lang3包依賴中,記得添加依賴

<dependency>
  <groupId>org.apache.commons</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.6</version>
</dependency>

Java版本:

/**
 *  執(zhí)行命令行,并等待命令執(zhí)行完畢,同時將過程中的控制臺輸出日志寫入日志文件中
 * @param cmd 命令,window記得要使用cmd /c開頭,如cmd /c ipconfig
 * @param dir 命令行所在路徑
 * @param logFile 日志文件
 * @throws IOException
 * @throws InterruptedException
 */
private void execCmdLine(String cmd, File dir, File logFile) throws IOException, InterruptedException {
    Process process = Runtime.getRuntime().exec(cmd, null, dir);
    InputStream inputStream = process.getInputStream();

    //開啟兩個線程用來讀取流,否則會造成死鎖問題
    new Thread(() -> {
        FileOutputStream fileOutputStream = null;
        TeeInputStream teeInputStream = null;
        BufferedReader bufferedReader = null;
        try {
            fileOutputStream = new FileOutputStream(logFile, true);
            //使用分流器,輸出日志文件
            teeInputStream = new TeeInputStream(inputStream, fileOutputStream);
            //這里gbk格式需要注意,我是在window上測試的,所以使用是gbk方式,如果是其他平臺,可能需要使用utf-8格式
            bufferedReader = new BufferedReader(new InputStreamReader(teeInputStream, "gbk"));
            String line;
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                bufferedReader.close();
                teeInputStream.close();
                fileOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }).start();
    new Thread(() -> {
        InputStreamReader err = new InputStreamReader(process.getErrorStream());
        BufferedReader bferr = new BufferedReader(err);
        String errline = "";
        try {
            while ((errline = bferr.readLine()) != null) {
                System.out.println("流錯誤:" + errline);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                bferr.close();
                err.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }).start();
    process.waitFor();
    process.destroy();
}

Kotlin版本:

/**
 * 執(zhí)行命令行,并等待命令執(zhí)行完畢,同時將過程中的控制臺輸出日志寫入日志文件中
 * - [cmd] 命令,window記得要使用cmd /c開頭,如cmd /c ipconfig
 * - [dir] 命令行所在路徑
 * - [logFile] 日志文件
 */
 fun execCmd(cmd: String, dir: File, logFile: File) {
    val process = Runtime.getRuntime().exec(cmd, null, dir)
    val inputStream = process.inputStream

    //開啟兩個線程用來讀取流,否則會造成死鎖問題
    thread {
        var fileOutputStream: FileOutputStream? = null
        var teeInputStream: TeeInputStream? = null
        var bufferedReader: BufferedReader? = null
        try {
            fileOutputStream = FileOutputStream(logFile, true)
            //使用分流器,日志文件和
            teeInputStream = TeeInputStream(inputStream, fileOutputStream)
            //區(qū)分不同平臺
            bufferedReader = if (isWin()) {
                BufferedReader(InputStreamReader(teeInputStream, "gbk"))
            } else {
                BufferedReader(InputStreamReader(teeInputStream, "utf-8"))
            }
            var line: String?
            while (bufferedReader.readLine().also { line = it } != null) {
                println(line)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } finally {
            try {
                bufferedReader!!.close()
                teeInputStream!!.close()
                fileOutputStream!!.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
    thread {
        val err = InputStreamReader(process.errorStream)
        val bferr = BufferedReader(err)
        var errline = ""
        try {
            while (bferr.readLine().also { errline = it } != null) {
                println("流錯誤:$errline")
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                bferr.close()
                err.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
    process.waitFor()
    process.destroy()
}

代碼封裝在庫中stars-one/common-controls: TornadoFx的常用控件 controls for tornadofx

參考

Java中 Process類的使用與注意事項說明

到此這篇關于關于Java執(zhí)行Cmd命令出現(xiàn)的死鎖問題解決的文章就介紹到這了,更多相關Java執(zhí)行Cmd命令死鎖內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

最新評論

岑溪市| 长海县| 刚察县| 称多县| 孟州市| 北川| 莒南县| 图木舒克市| 黄陵县| 霍邱县| 辽中县| 略阳县| 广昌县| 体育| 太原市| 静宁县| 耒阳市| 双流县| 云和县| 阜新| 洛扎县| 浙江省| 五原县| 林州市| 南京市| 增城市| 湘潭县| 华宁县| 津南区| 睢宁县| 原阳县| 富顺县| 隆子县| 房产| 屏边| 岳池县| 宜良县| 重庆市| 诸城市| 井冈山市| 广安市|