欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

問(wèn)題

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

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

原因及解決方法

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

如果該可執(zhí)行程序的輸入、輸出或者錯(cuò)誤輸出比較多的話(huà),而由于運(yùn)行窗口的標(biāo)準(zhǔn)輸入、輸出等緩沖區(qū)有大小的限制,則可能導(dǎo)致子進(jìn)程阻塞,甚至產(chǎn)生死鎖

其解決方法就是在waitfor()方法之前讀出窗口的標(biāo)準(zhǔn)輸出、輸出、錯(cuò)誤緩沖區(qū)中的內(nèi)容。

方法封裝

下面代碼中的TeeInputStream是在lang3包依賴(lài)中,記得添加依賴(lài)

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

Java版本:

/**
 *  執(zhí)行命令行,并等待命令執(zhí)行完畢,同時(shí)將過(guò)程中的控制臺(tái)輸出日志寫(xiě)入日志文件中
 * @param cmd 命令,window記得要使用cmd /c開(kāi)頭,如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();

    //開(kāi)啟兩個(gè)線(xiàn)程用來(lái)讀取流,否則會(huì)造成死鎖問(wèn)題
    new Thread(() -> {
        FileOutputStream fileOutputStream = null;
        TeeInputStream teeInputStream = null;
        BufferedReader bufferedReader = null;
        try {
            fileOutputStream = new FileOutputStream(logFile, true);
            //使用分流器,輸出日志文件
            teeInputStream = new TeeInputStream(inputStream, fileOutputStream);
            //這里gbk格式需要注意,我是在window上測(cè)試的,所以使用是gbk方式,如果是其他平臺(tái),可能需要使用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("流錯(cuò)誤:" + 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í)行完畢,同時(shí)將過(guò)程中的控制臺(tái)輸出日志寫(xiě)入日志文件中
 * - [cmd] 命令,window記得要使用cmd /c開(kāi)頭,如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

    //開(kāi)啟兩個(gè)線(xiàn)程用來(lái)讀取流,否則會(huì)造成死鎖問(wèn)題
    thread {
        var fileOutputStream: FileOutputStream? = null
        var teeInputStream: TeeInputStream? = null
        var bufferedReader: BufferedReader? = null
        try {
            fileOutputStream = FileOutputStream(logFile, true)
            //使用分流器,日志文件和
            teeInputStream = TeeInputStream(inputStream, fileOutputStream)
            //區(qū)分不同平臺(tái)
            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("流錯(cuò)誤:$errline")
            }
        } catch (e: Exception) {
            e.printStackTrace()
        } finally {
            try {
                bferr.close()
                err.close()
            } catch (e: IOException) {
                e.printStackTrace()
            }
        }
    }
    process.waitFor()
    process.destroy()
}

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

參考

Java中 Process類(lèi)的使用與注意事項(xiàng)說(shuō)明

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

相關(guān)文章

  • Java中將UUID存儲(chǔ)為Base64字符串的方法實(shí)現(xiàn)

    Java中將UUID存儲(chǔ)為Base64字符串的方法實(shí)現(xiàn)

    使用Base64編碼來(lái)對(duì)UUID存儲(chǔ)在一些特定的場(chǎng)合被廣泛的使用,本文主要介紹了Java中將UUID存儲(chǔ)為Base64字符串的方法實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-04-04
  • Java可以如何實(shí)現(xiàn)文件變動(dòng)的監(jiān)聽(tīng)的示例

    Java可以如何實(shí)現(xiàn)文件變動(dòng)的監(jiān)聽(tīng)的示例

    本篇文章主要介紹了Java可以如何實(shí)現(xiàn)文件變動(dòng)的監(jiān)聽(tīng)的示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • 詳解Spring Boot中使用@Scheduled創(chuàng)建定時(shí)任務(wù)

    詳解Spring Boot中使用@Scheduled創(chuàng)建定時(shí)任務(wù)

    本篇文章中主要介紹了Spring Boot中使用@Scheduled創(chuàng)建定時(shí)任務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • Java實(shí)現(xiàn)計(jì)算機(jī)程序設(shè)計(jì)思路

    Java實(shí)現(xiàn)計(jì)算機(jī)程序設(shè)計(jì)思路

    這篇文章主要為大家介紹了Java實(shí)現(xiàn)計(jì)算機(jī)程序設(shè)計(jì)思路,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Java多線(xiàn)程中的Future類(lèi)詳細(xì)解讀

    Java多線(xiàn)程中的Future類(lèi)詳細(xì)解讀

    這篇文章主要介紹了Java多線(xiàn)程中的Future類(lèi)詳細(xì)解讀,Future表示一個(gè)可能還沒(méi)有完成的異步任務(wù)的結(jié)果,針對(duì)這個(gè)結(jié)果可以添加Callback以便在任務(wù)執(zhí)行成功或失敗后作出相應(yīng)的操作,需要的朋友可以參考下
    2023-11-11
  • JVM 方法調(diào)用之動(dòng)態(tài)分派(詳解)

    JVM 方法調(diào)用之動(dòng)態(tài)分派(詳解)

    下面小編就為大家?guī)?lái)一篇JVM 方法調(diào)用之動(dòng)態(tài)分派(詳解)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • Java利用遺傳算法求解最短路徑問(wèn)題

    Java利用遺傳算法求解最短路徑問(wèn)題

    遺傳算法(Genetic Algorithm,GA)最早是由美國(guó)的John holland于20世紀(jì)70年代提出,該算法是根據(jù)大自然中生物體進(jìn)化規(guī)律而設(shè)計(jì)提出的。本文將利用遺傳算法求解最短路徑問(wèn)題,需要的可以參考一下
    2022-06-06
  • Spring詳細(xì)解讀事務(wù)管理

    Spring詳細(xì)解讀事務(wù)管理

    Spring事務(wù)的本質(zhì)就是對(duì)數(shù)據(jù)庫(kù)事務(wù)的支持,沒(méi)有數(shù)據(jù)庫(kù)事務(wù),Spring是無(wú)法提供事務(wù)功能的。Spring只提供統(tǒng)一的事務(wù)管理接口,具體實(shí)現(xiàn)都是由數(shù)據(jù)庫(kù)自己實(shí)現(xiàn)的,Spring會(huì)在事務(wù)開(kāi)始時(shí),根據(jù)當(dāng)前設(shè)置的隔離級(jí)別,調(diào)整數(shù)據(jù)庫(kù)的隔離級(jí)別,由此保持一致
    2022-04-04
  • java中request常用方法小結(jié)

    java中request常用方法小結(jié)

    這篇文章主要介紹了java中request常用方法小結(jié),需要的朋友可以參考下
    2014-10-10
  • Java Swing組件下拉菜單控件JComboBox用法示例

    Java Swing組件下拉菜單控件JComboBox用法示例

    這篇文章主要介紹了Java Swing組件下拉菜單控件JComboBox用法,結(jié)合具體實(shí)例形式分析了Swing組件下拉菜單控件JComboBox的具體定義、使用方法及相關(guān)使用注意事項(xiàng),需要的朋友可以參考下
    2017-11-11

最新評(píng)論