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

java調(diào)用process線程阻塞問(wèn)題的解決

 更新時(shí)間:2021年06月09日 08:35:59   作者:遺失的歲月  
這篇文章主要介紹了java調(diào)用process線程阻塞問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

java調(diào)用process線程阻塞問(wèn)題

項(xiàng)目需求中涉及java調(diào)用.bat文件進(jìn)行圖像處理,先直接上簡(jiǎn)略版程序

public void draw(){
        //調(diào)用bat腳本進(jìn)行圖像處理
        Process process = null;
        InputStream in = null;
        try {
            process = Runtime.getRuntime().exec("startup.bat");
            //輸出測(cè)試
//            in = process.getInputStream();
//            String line;
//            BufferedReader br = new BufferedReader(new InputStreamReader(in));
//            while ((line = br.readLine()) != null) {
//                System.out.println(line);
//            }
            //等待
            process.waitFor();
        } catch (Exception e) {
        } finally {
            process.destroy();
        }
    }

JAVA使用遇到的問(wèn)題描述

一般需要調(diào)用系統(tǒng)命令時(shí),大部分人第一反應(yīng)肯定是使用Runtime.getRuntime().exec(command)返回一個(gè)process對(duì)象,再調(diào)用process.waitFor()來(lái)等待命令執(zhí)行結(jié)束,獲取執(zhí)行結(jié)果。

調(diào)試的時(shí)候發(fā)現(xiàn)異?,F(xiàn)象,process.waitFor();一直沒(méi)有結(jié)束,導(dǎo)致線程阻塞再次,強(qiáng)行關(guān)閉程序后,發(fā)現(xiàn)圖像處理只進(jìn)行了一部分。

根據(jù)現(xiàn)象并查看了JDK的幫助文檔,如下

如有必要,一直要等到由該 Process 對(duì)象表示的進(jìn)程已經(jīng)終止。如果已終止該子進(jìn)程,此方法立即返回。但是直接調(diào)用這個(gè)方法會(huì)導(dǎo)致當(dāng)前線程阻塞,直到退出子進(jìn)程。

對(duì)此JDK文檔上還有如此解釋:因?yàn)楸镜氐南到y(tǒng)對(duì)標(biāo)準(zhǔn)輸入和輸出所提供的緩沖池有效,所以錯(cuò)誤的對(duì)標(biāo)準(zhǔn)輸出快速的寫入何從標(biāo)準(zhǔn)輸入快速的讀入都有可能造成子進(jìn)程的阻塞,甚至死鎖。

Process執(zhí)行邏輯

* 主進(jìn)程中調(diào)用Runtime.exec會(huì)創(chuàng)建一個(gè)子進(jìn)程,用于執(zhí)行腳本。子進(jìn)程創(chuàng)建后會(huì)和主進(jìn)程分別獨(dú)立運(yùn)行。

* 創(chuàng)建的子進(jìn)程沒(méi)有自己的終端或控制臺(tái)。它的所有標(biāo)準(zhǔn) io(即 stdin、stdout 和 stderr)操作都將通過(guò)三個(gè)流 (getOutputStream()、getInputStream() 和 getErrorStream()) 重定向到父進(jìn)程。父進(jìn)程使用這些流來(lái)提供到子進(jìn)程的輸入和獲得從子進(jìn)程的輸出。

* 這時(shí)候子進(jìn)程不斷向主進(jìn)程發(fā)生數(shù)據(jù),而主進(jìn)程調(diào)用Process.waitfor后已掛起。當(dāng)前子進(jìn)程和主進(jìn)程之間的緩沖區(qū)塞滿后,子進(jìn)程不能繼續(xù)寫數(shù)據(jù),然后也會(huì)掛起。

* 這樣子進(jìn)程等待主進(jìn)程讀取數(shù)據(jù),主進(jìn)程等待子進(jìn)程結(jié)束,兩個(gè)進(jìn)程相互等待,最終導(dǎo)致死鎖。

解決方法:

在waitFor()之前,利用單獨(dú)兩個(gè)線程,分別處理process的getInputStream()和getErrorSteam(),防止緩沖區(qū)被撐滿,導(dǎo)致阻塞;

修改后代碼

public class test {
    public void draw(){
        //調(diào)用bat腳本進(jìn)行圖像處理
        Process process = null;
        InputStream in = null;
        try {
            process = Runtime.getRuntime().exec("startup.bat");
            //輸出測(cè)試
//            in = process.getInputStream();
//            String line;
//            BufferedReader br = new BufferedReader(new InputStreamReader(in));
//            while ((line = br.readLine()) != null) {
//                System.out.println(line);
//            }
            //新啟兩個(gè)線程
            new DealProcessSream(process.getInputStream()).start();
            new DealProcessSream(process.getErrorStream()).start();
            process.waitFor();
        } catch (Exception e) {
        } finally {
            process.destroy();
        }
    }
}
public class DealProcessSream extends Thread {
    private InputStream inputStream;
    public DealProcessSream(InputStream inputStream) {
        this.inputStream = inputStream;
    }
    public void run() {
        InputStreamReader inputStreamReader = null;
        BufferedReader br = null;
        try {
            inputStreamReader = new InputStreamReader(
                    inputStream);
            br = new BufferedReader(inputStreamReader);
            // 打印信息
//            String line = null;
//            while ((line = br.readLine()) != null) {
//                System.out.println(line);
//            }
            // 不打印信息
           while (br.readLine() != null);
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }finally {
            try {
                br.close();
                inputStreamReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Process對(duì)象.waitFor()的阻塞問(wèn)題(坑)

有時(shí)需要在程序中調(diào)用可執(zhí)行程序或腳本命令:

Process process = Runtime.getRuntime().exec(shPath);
int exitCode = process .waitFor();

Runtime.getRuntime()返回當(dāng)前應(yīng)用程序的Runtime對(duì)象,該對(duì)象的exec()方法指示Java虛擬機(jī)創(chuàng)建一個(gè)子進(jìn)程執(zhí)行指定的可執(zhí)行程序,

并返回與該子進(jìn)程對(duì)應(yīng)的Process對(duì)象實(shí)例。通過(guò)Process可以控制該子進(jìn)程的執(zhí)行或獲取該子進(jìn)程的信息。

它的所有標(biāo)準(zhǔn)io(即stdin,stdout,stderr)操作都將通過(guò)三個(gè)流(getOutputStream(),getInputStream(),getErrorStream())重定向到父進(jìn)程。

父進(jìn)程使用這些流來(lái)提供到子進(jìn)程的輸入和獲得從子進(jìn)程的輸出。因?yàn)橛行┍緳C(jī)平臺(tái)僅針對(duì)標(biāo)準(zhǔn)輸入和輸出流提供有限的緩沖區(qū)大小,如果讀

寫子進(jìn)程的輸出流或輸入流出現(xiàn)失敗,則可能導(dǎo)致子進(jìn)程阻塞,甚至產(chǎn)生死鎖。(如果程序不斷在向標(biāo)準(zhǔn)輸出流和標(biāo)準(zhǔn)錯(cuò)誤流寫數(shù)據(jù),而JVM不讀取的話,當(dāng)緩沖區(qū)滿之后將無(wú)法繼續(xù)寫入數(shù)據(jù),最終造成阻塞在waifor()這里。)

process .getErrorStream():獲得子進(jìn)程的錯(cuò)誤輸出流

process .getInputStream():獲得子進(jìn)程的普通輸出流

簡(jiǎn)單示例:

Process shellProcess = null;
    try {
 
      shellProcess = Runtime.getRuntime().exec(shPath);
      shellErrorResultReader = new BufferedReader(new InputStreamReader(shellProcess.getErrorStream()));
      shellInfoResultReader =  new BufferedReader(new InputStreamReader(shellProcess.getInputStream()));
      String infoLine;
      while ((infoLine = shellInfoResultReader.readLine()) != null) {
        logger.info("腳本文件執(zhí)行信息:{}", infoLine);
      }
      String errorLine;
      while ((errorLine = shellErrorResultReader.readLine()) != null) {
        logger.warn("腳本文件執(zhí)行信息:{}", errorLine);
      }
      // 等待程序執(zhí)行結(jié)束并輸出狀態(tài)
      exitCode = shellProcess.waitFor();
      if (0 == exitCode) {
        logger.info("腳本文件執(zhí)行成功:" + exitCode);
      } else {
        logger.error("腳本文件執(zhí)行失敗:" + exitCode);
      }
    } catch (Exception e) {
      logger.error("shell腳本執(zhí)行錯(cuò)誤", e);
    } finally {
      if (null != shellInfoResultReader) {
        try {
          shellInfoResultReader.close();
        } catch (IOException e) {
          logger.error("流文件關(guān)閉異常:", e);
        }
      }
      if (null != shellErrorResultReader) {
        try {
          shellErrorResultReader.close();
        } catch (IOException e) {
          logger.error("流文件關(guān)閉異常:", e);
        }
      }
      if (null != shellProcess) {
        shellProcess.destroy();
      }
}

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java類中使用Jfreechart的簡(jiǎn)單實(shí)例

    java類中使用Jfreechart的簡(jiǎn)單實(shí)例

    這篇文章介紹了java類中使用Jfreechart的簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下
    2013-08-08
  • JAVA中的隊(duì)列(Queue)詳解

    JAVA中的隊(duì)列(Queue)詳解

    這篇文章主要介紹了JAVA中的隊(duì)列(Queue)詳解,隊(duì)列是一種特殊的線性表,遵循先入先出、后入后出的基本原則,一般來(lái)說(shuō),它只允許在表的前端進(jìn)行刪除操作,需要的朋友可以參考下
    2023-07-07
  • 記一次springboot服務(wù)凌晨無(wú)故宕機(jī)問(wèn)題的解決

    記一次springboot服務(wù)凌晨無(wú)故宕機(jī)問(wèn)題的解決

    這篇文章主要介紹了記一次springboot服務(wù)凌晨無(wú)故宕機(jī)問(wèn)題的解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-09-09
  • Nacos配置中心搭建及動(dòng)態(tài)刷新配置及踩坑記錄

    Nacos配置中心搭建及動(dòng)態(tài)刷新配置及踩坑記錄

    這篇文章主要介紹了Nacos配置中心搭建及動(dòng)態(tài)刷新配置及踩坑記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • java實(shí)現(xiàn)帶有背景圖片的窗體

    java實(shí)現(xiàn)帶有背景圖片的窗體

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)帶有背景圖片的窗體,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-03-03
  • 如何從request中獲取body的數(shù)據(jù)

    如何從request中獲取body的數(shù)據(jù)

    這篇文章主要介紹了如何從request中獲取body的數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • SpringBoot+Quartz+數(shù)據(jù)庫(kù)存儲(chǔ)的完美集合

    SpringBoot+Quartz+數(shù)據(jù)庫(kù)存儲(chǔ)的完美集合

    這篇文章主要介紹了SpringBoot+Quartz+數(shù)據(jù)庫(kù)存儲(chǔ)的示例代碼,本文通過(guò)實(shí)例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-02-02
  • springcloud之Feign、ribbon如何設(shè)置超時(shí)時(shí)間和重試機(jī)制

    springcloud之Feign、ribbon如何設(shè)置超時(shí)時(shí)間和重試機(jī)制

    這篇文章主要介紹了springcloud之Feign、ribbon如何設(shè)置超時(shí)時(shí)間和重試機(jī)制,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 如何解決java.lang.ClassNotFoundException: com.mysql.jdbc.Driver問(wèn)題

    如何解決java.lang.ClassNotFoundException: com.mysql.jdbc.Dr

    這篇文章主要介紹了如何解決java.lang.ClassNotFoundException: com.mysql.jdbc.Driver問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-12-12
  • Rabbitmq消息推送功能實(shí)現(xiàn)示例

    Rabbitmq消息推送功能實(shí)現(xiàn)示例

    rabbitMQ為異步消息處理提出了一個(gè)很好的解決方案,它是一個(gè)非常好用的消息中間件。主要解決當(dāng)生產(chǎn)者大量產(chǎn)生數(shù)據(jù)時(shí),消費(fèi)者無(wú)法快速消費(fèi)的問(wèn)題。這個(gè)時(shí)候需要一個(gè)中間層,保存這個(gè)數(shù)據(jù),rabbitMQ是一個(gè)很好的解決方案
    2022-12-12

最新評(píng)論