java - 为什么我在 Linux 中使用 ExecutorService 读取线程流时得到 "java.io.IOException: Stream closed"?

标签 java bash concurrency inputstream executorservice

我有一个 java 程序,它使用执行器和线程池 ping 一个 IP 地址列表,并将结果打印在屏幕上。

它在 Windows 环境中工作正常,但是当我在 Linux 中运行它时,我经常收到“java.io.IOException:流已关闭”错误。但不适用于所有线程。

Name_49: xxx.xxx.xxx.3: 2.558
Name_50: xxx.xxx.xxx.56: 0.419
Name_44: Endsjava.io.IOException: Stream closed
    at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
    at java.io.BufferedInputStream.read(BufferedInputStream.java:325)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)

这是我的主要行动:

ArrayList<String> ips= new ArrayList<>();
    elements.add("123.123.123.123");
// etc..

 ExecutorService executor = (ExecutorService) Executors.newCachedThreadPool();
    List<Task> taskList = new ArrayList<>();
    for (int i = 0; i < ips.size(); i++) {
        Task task = new Task("Name_"+ i, elements.get(i));
        taskList.add(task);
    }

    List<Future<Result>> resultList = null;

    try {
        resultList = executor.invokeAll(taskList);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }

    executor.shutdown();

    System.out.println("Main: Printing the results");
    for (int i = 0; i < resultList.size(); i++) {
        Future<Result> future = resultList.get(i);
        try {
            Result result = future.get();
            System.out.println(result.getName() + ": " + result.getIP() + ": " + result.getPing() );
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }

ping 发生在带有结果对象的可调用类中:

public class Task implements Callable<Result> {

private String name;
private String ping;
private String ip;

public Task(String name, String ip) {
    this.name = name;
    this.ip = ip;
}

@Override
public Result call() throws Exception {
    System.out.printf("%s: Starting\n", this.name);

    Result result = new Result();
    String resultstr = linuxPingServer(this.ip);
    //String resultstr = winPingServer(this.ip);

    result.setName(this.name);
    result.setIP(this.ip);
    result.setPing(resultstr);

    System.out.println(this.name + ": Ends");
    return result;
}

private String runCMD(String cmd) {
    Process p = null;
    ReadStream s1 = null;
    ReadStream s2 = null;
    String outerr = "";
    String outstd = "";
    String output = "";

    try {
        p = Runtime.getRuntime().exec(cmd);

        s1 = new ReadStream("stdin", p.getInputStream());
        s2 = new ReadStream("stderr", p.getErrorStream());
        s1.start();
        s2.start();
        p.waitFor();

        //s2.returnOut();
        outstd = s1.returnOut();
        outerr = s2.returnOut();

        if (outstd != null && !outstd.isEmpty()) {
            output = outstd;
        } else //if (outerr != null && !outerr.isEmpty())
        {
            output = outerr;
        }

    } catch (IOException | InterruptedException ex) {
        System.out.println("StreamCheck_Exception - BashExec" + ex.getMessage());
    } finally {
        if (p != null) {
            p.destroy();
        }
    }
    return output;
}

public String linuxPingServer(String ip) {

    // Ping with reduced interval ( -i 0.1secs)
    // ping count = 5
    String pingCMD = "ping -i 0.1 -c5 " + ip;

    String result1 = "";
    String result2 = "";
    String result3 = "";

    result1 = runCMD(pingCMD);

    // split string on end of line
    String[] lines = result1.split(System.getProperty("line.separator"));

    // get statistics ( ussually last line )
    result2 = lines[lines.length - 1];

    // parse result -avg is third value ( fifth "/" )
    lines = result2.split("/");
    result3 = lines[4];

    return result3;

}

这是我的读者类别:

public class ReadStream implements Runnable {
String name;
InputStream is;
Thread thread;      
StringBuffer output;

public ReadStream(String name, InputStream is) {
    this.name = name;
    this.is = is;
    this.output = new StringBuffer();
}       

public void start () {
    thread = new Thread (this);
    thread.start ();
}       

public void run () {
    try {
        InputStreamReader isr = new InputStreamReader (is);
        BufferedReader br = new BufferedReader (isr);   
        while (true) {
            String s = br.readLine ();
            if (s == null) break;
            this.output.append(s + "\n");
        }
        is.close ();    
    } catch (Exception ex) {
        System.out.println ("Problem reading stream " + name + "... :" + ex);
        ex.printStackTrace ();
    }
}

我很困惑为什么会发生这种情况。有人可以向我解释一下我正在执行的操作有什么问题吗?

已编辑 - 更多跟踪 -

java -jar WinThreadPing.jar
Name_0: Starting
Name_52: Starting
Name_50: Starting
Name_51: Starting
Name_53: Starting
Name_48: Starting
Name_47: Starting
//.. more Starting threads
Name_98: Staring
Name_99: Staring
Name_59: Ends
Name_57: Ends
Name_60: Ends
Name_56: Ends
Name_45: Ends
Name_50: Ends
Name_48: Ends
Name_51: Ends
Name_39: Ends
Name_52: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
Name_43: Ends
java.io.IOException: Stream closedName_53: Ends
Name_42: Ends

Name_38: Ends
        at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
Name_47: Ends   at java.io.BufferedInputStream.read(BufferedInputStream.java:325)

        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
Problem reading stream stdin... :java.io.IOException: Stream closed     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)

        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:154)
        at java.io.BufferedReader.readLine(BufferedReader.java:317)
Name_34: Ends   at java.io.BufferedReader.readLine(BufferedReader.java:382)
        at WinThreadedPing.ReadStream.run(ReadStream.java:40)
        at java.lang.Thread.run(Thread.java:745)

java.io.IOException: Stream closedName_36: Ends

        at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:272)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
Problem reading stream stdin... :java.io.IOException: Stream closed     at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)

        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:154)
        at java.io.BufferedReader.readLine(BufferedReader.java:317)
Name_44: Ends   at java.io.BufferedReader.readLine(BufferedReader.java:382)
        at WinThreadedPing.ReadStream.run(ReadStream.java:40)
        at java.lang.Thread.run(Thread.java:745)
java.io.IOException: Stream closed
        at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
        at java.io.BufferedInputStream.read1(BufferedInputStream.java:272)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:334)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)

Name_46: Ends
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
        at java.io.BufferedReader.fill(BufferedReader.java:154)Name_29: Ends

        at java.io.BufferedReader.readLine(BufferedReader.java:317)
        at java.io.BufferedReader.readLine(BufferedReader.java:382)
        at WinThreadedPing.ReadStream.run(ReadStream.java:40)
        at java.lang.Thread.run(Thread.java:745)
Name_27: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
Problem reading stream stdin... :java.io.IOException: Stream closed
Name_26: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
Name_22: Ends
Name_28: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
java.io.IOException: Stream closed
Problem reading stream stdin... :java.io.IOException: Stream closed
        at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)Problem reading stream stdin... :java.io.IOException: Stream closed

        at java.io.BufferedInputStream.read(BufferedInputStream.java:325)Name_23: Ends
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)

        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)Problem reading stream stdin... :java.io.IOException: Stream closed
        at java.io.InputStreamReader.read(InputStreamReader.java:184)

Name_17: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
Name_15: Ends
Name_18: Ends
Name_16: Ends
        at java.io.BufferedReader.fill(BufferedReader.java:154)
        at java.io.BufferedReader.readLine(BufferedReader.java:317)
Problem reading stream stdin... :java.io.IOException: Stream closed
        at java.io.BufferedReader.readLine(BufferedReader.java:382)
Name_20: Ends   at WinThreadedPing.ReadStream.run(ReadStream.java:40)
Name_14: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
Problem reading stream stdin... :java.io.IOException: Stream closed

        at java.lang.Thread.run(Thread.java:745)Name_10: Ends

Problem reading stream stdin... :java.io.IOException: Stream closed
Name_19: Endsjava.io.IOException: Stream closed

Name_7: Ends
Name_8: Ends
        at java.io.BufferedInputStream.getBufIfOpen(BufferedInputStream.java:162)
        at java.io.BufferedInputStream.read(BufferedInputStream.java:325)
        at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
        at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
        at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
        at java.io.InputStreamReader.read(InputStreamReader.java:184)
Name_11: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
Name_4: Ends
Problem reading stream stdin... :java.io.IOException: Stream closed
Name_5: Ends    at java.io.BufferedReader.fill(BufferedReader.java:154)

        at java.io.BufferedReader.readLine(BufferedReader.java:317)
        at java.io.BufferedReader.readLine(BufferedReader.java:382)
        at WinThreadedPing.ReadStream.run(ReadStream.java:40)
        at java.lang.Thread.run(Thread.java:745)
Problem reading stream stdin... :java.io.IOException: Stream closed
Name_62: Ends
//..etc

最佳答案

我正在回答我自己的问题。

经过一些实验,我能够使用 ProcessBuilder 纠正该问题。以及 ProcessBuilder OpenFiles 的答案问题:

ProcessBuilder pb = new ProcessBuilder("bash", "-c", cmd);

        pb.redirectError(new File(this.Filepath + ".err"));
        pb.redirectOutput(new File(this.Filepath));

        Process shell = pb.start();

        //shell.wait();
        int exitVal= shell.waitFor();

        //missing these was causing the mass amounts of open 'files'
        shell.getInputStream().close();
        shell.getOutputStream().close();
        shell.getErrorStream().close();

关于java - 为什么我在 Linux 中使用 ExecutorService 读取线程流时得到 "java.io.IOException: Stream closed"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28409132/

相关文章:

java - 组件导航

java - Camel可以用Reactor代替吗,如果可以,那么如何正确完成呢?

bash - Bash 脚本获取自身完整路径的可靠方法

java - 从另一个线程调用一个线程的方法会暂停线程执行吗?

javascript - jQuery触发函数是否保证同步

JAVA - 根据参数从抽象类创建对象

java - 如何在Java代码中将IST日期除以正常日期?

linux - Bash 脚本 : too many arguments in [ test ]

regex - Perl 的\K in bash 函数

c++ - 了解 std::hardware_破坏性_interference_size 和 std::hardware_constructive_interference_size