Process. getInputStream () 차단 문제

8403 단어 자바
자바 에서 Runtime. getInstance (). exec (String cmd) 나 new ProcessBuilder (String cmd). start () 는 하위 프로 세 스 대상 Process 를 생 성 할 수 있 습 니 다.process 대상 을 호출 하 는 waitFor () 방법 을 통 해 메 인 프로 세 스 를 대기 상태 로 들 어가 하위 프로 세 스 가 실 행 될 때 까지 다음 작업 을 진행 할 수 있 습 니 다.하위 프로 세 스 를 잘못 처리 하면 메 인 프로 세 스 가 막 혀 프로그램 전체 가 죽 을 수 있 습 니 다.
자바 Api 에서 Process 에 대해 말 하 는 것 은:
ProcessBuilder. start () 와 Runtime. exec 방법 으로 이 컴퓨터 프로 세 스 를 만 들 고 Process 하위 클래스 의 인 스 턴 스 를 되 돌려 줍 니 다. 이 인 스 턴 스 는 프로 세 스 를 제어 하고 관련 정 보 를 얻 을 수 있 습 니 다.프로 세 스 클래스 는 프로 세 스 입력, 출력 실행, 프로 세 스 완료 대기, 프로 세 스 종료 상태 검사, 프로 세 스 를 없 애 는 방법 을 제공 합 니 다.
프로 세 스 를 만 드 는 방법 은 이 컴퓨터 플랫폼 의 특정 프로 세 스 를 잘 작 동 하지 못 할 수도 있 습 니 다. 예 를 들 어 이 컴퓨터 창 프로 세 스, 데 몬, Microsoft Windows 의 Win 16/DOS 프로 세 스, 셸 스 크 립 트 등 입 니 다.만 든 하위 프로 세 스 는 터미널 이나 콘 솔 이 없습니다.모든 표준 io (즉 stdin, stdout, stderr) 작업 은 세 개의 흐름 (getOutputStream (), getInputStream (), getErrorStream () 을 통 해 부모 프로 세 스 로 재 설정 합 니 다.부모 프로 세 스 는 이 흐름 을 사용 하여 하위 프로 세 스 의 입력 과 하위 프로 세 스에 서 출력 을 가 져 옵 니 다.일부 이 플랫폼 은 표준 입력 과 출력 흐름 에 만 제 한 된 버퍼 크기 를 제공 하기 때문에 읽 기 쓰기 서브 프로 세 스 의 출력 흐름 이나 입력 흐름 이 신속하게 실패 하면 서브 프로 세 스 가 막 히 고 심지어 잠 금 이 생 길 수 있 습 니 다.getOutputStream (), getInputStream (), getErrorStream () 에 대한 설명 에서 주의사항 이 있 습 니 다. 출력 흐름 과 오류 흐름 을 버퍼 링 하 는 것 은 좋 은 생각 입 니 다!응, 추상 적 이 야!
문 제 는 바로 여기에 있 습 니 다. Process. getInputStream () 과 Process. getErrorStream () 은 각각 Process 의 표준 출력 흐름 과 오류 흐름 을 되 돌려 줍 니 다. 두 흐름 이 잘못 처리 되면 버퍼 가 제때에 제거 되 지 않 고 가득 차 면 프로 세 스 가 막 힙 니 다. Process. destory () 를 호출 하 더 라 도 막 힌 하위 프로 세 스 를 없 앨 수 있 는 것 은 아 닙 니 다.
Process 의 출력 흐름 과 오류 흐름 을 동기 화하 여 처리 하려 고 시도 하면 반드시 효과 가 있 는 것 은 아 닙 니 다. 순서 실행 과정 에서 출력 흐름 과 오류 흐름 은 제때에 처리 되 지 못 합 니 다.해결 방안 은 두 가지 가 있다.
프로젝트 1: process 의 출력 흐름 과 오류 흐름 을 동시에 가 져 옵 니 다.
두 스 레 드 를 시작 하여 출력 흐름 과 오류 흐름 을 동시에 읽 고 처리 합 니 다. IDE 를 열기 가 귀 찮 습 니 다. 코드 를 대충 두 드 려 보 세 요. 오류 가 있 을 수 있 습 니 다. 다음 과 같 습 니 다.
호출 자:
class ProcessExecutor
{
    private Process p;
    private List outputList;
    private List errorOutputList;
    public ProcessExecutor(Process p) throws IOException
    {
        if(null == p)
        {
            throw new IOException("the provided Process is null");
        }
        this. p = p;
    }
    public List getOutputList()
    {
        return this. outputList;
    }
    public List getErrorOutputList()
    {
        return this.errorOutputList;
    }
    public int execute()
    {
        int rs = 0;
        Thread outputThread = new ProcessOutputThread(this.p.getInputStream());
        Thread errorOutputThread = new ProcessOutputThread(this.p.getErrorStream());
        outputThread.start();
        errorOutputThread.start();
        rs = p.waitFor();
        outputThread.join();
        errorOutputThread.join();
        this.outputList = outputThread.getOutputList();
        this.errorOutputList = errorOutputThread.getOutputList();
        return rs;
    }
}

흐름 처리 스 레 드
class ProcessOutputThread extends Thread
{
    private InputStream is;
    private List outputList;
    public ProcessOutputThread(InputStream is) throws IOException
    {
        if(null == is)
        {
            throw new IOException("the provided InputStream is null");
        }
        this. is = is;
        this.outputList = new ArrayList();
    }
    public List getOutputList()
    {
        return this. outputList;
    }
    @Override
    public void run()
    {
        InputStreamReader ir = null;
        BufferedReader br = null;
        try
        {
            ir = new InputStreamReader(this.is);
            br = new BufferedReader(ir);
            String output = null;
            while(null != (output = br.readLine()))
            {
                print(output);
                this.outputList.add(output);
            }
        }
        catch(IOException e)
        {
            e.print();
        }
        finally
        (
            try
            {
                if(null != br)
                {
                    br.close();
                }
                if(null != ir)
                {
                    ir.close();
                }
                if(null != this.is)
                {
                    this.is.close();
                }
            }
            catch(IOException e)
            {
                e.print();
            }
        )
    }
}

프로젝트 2: ProcessBuilder 의 redirect ErrorStream () 방법 으로 출력 흐름 과 오류 흐름 을 합 칩 니 다.(이 방법 은 검증 이 통과 되 지 않 았 습 니 다)
public int execute()
{
    int rs = 0;
    String[] cmds = {...};//command and arg  
    ProcessBuilder builder = new ProcessBuilder(cmds);  
    builder.redirectErrorStream(true);  
    Process process = builder.start();  
    BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()));  
    String output = null;  
    while (null != (readLine = br.readLine()))
    {  
        print(output);   
    }  
    rs = process.waitFor();
    return rs;
} 

다음으로 전송:http://blog.csdn.net/dancen/article/details/7969328#

좋은 웹페이지 즐겨찾기