系统输出(System.out)和错误输出(System.err)的随机打印顺序

4
请看下面的代码片段:
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class ReadFile {


    public static void main(String[] args)  {

        String str="";
        FileReader fileReader=null;

        try{


            // I am running on windows only  & hence the path :) 
            File file=new File("D:\\Users\\jenco\\Desktop\\readme.txt");
            fileReader=new FileReader(file);
            BufferedReader bufferedReader=new BufferedReader(fileReader);
            while((str=bufferedReader.readLine())!=null){
                System.err.println(str);
            }

        }catch(Exception exception){
            System.err.println("Error occured while reading the file : " + exception.getMessage());
            exception.printStackTrace();
        }
        finally {
            if (fileReader != null) {
                try {
                    fileReader.close();
                    System.out.println("Finally is executed.File stream is closed.");
                } catch (IOException ioException) {

                    ioException.printStackTrace();
                }
            }
        }

    }

}

当我多次执行代码时,输出的结果是随机的。有时候System.out语句会先在控制台中打印,有时候System.err会先打印。以下是我得到的随机输出结果。

输出1

Finally is executed.File stream is closed.
this is a text file 
and a java program will read this file.

输出 2

this is a text file 
and a java program will read this file.
Finally is executed.File stream is closed.

为什么会这样呢?

是因为缓冲读取器的原因吗? - Tito
我原以为 stderr 会被缓存,但是我可能错了。 - MadProgrammer
3个回答

6
我认为这是因为您正在写入两个不同的输出(一个是标准输出,另一个是标准错误)。在Java执行期间,它们可能由两个不同的线程处理,以允许同时写入。假设是这种情况,那么CPU任务调度器不会每次按相同顺序执行线程。如果您的所有输出都将发送到同一个输出流中(即所有内容都发送到标准输出或标准错误),则永远不会得到此功能。您将无法保证标准错误与标准输出的执行顺序。

4
不需要讨论两个不同的线程...关键是标准输出和错误输出在这里是不同的流 :-) - obataku

1

因为在您的情况下,System.out和System.err都指向控制台。

为了证明,如果在println()之后添加System.out.flush()和System.err.flush(),则输出将保持一致。


0

这个问题已经在这里得到了解答:

Java: System.out.println和System.err.println顺序错乱

这是因为你的finally子句使用了System.out,而其他代码使用了System.err。err流会在out流之前或之后刷新。

因此,打印数据的顺序不能保证与调用顺序相同。

你可以将控制台将err流定向到文件,或将out流定向到文件以供以后检查。或者,修改你的代码将所有内容都打印到System.out。许多程序员不使用err,其实用性也有争议,除非你将err与控制台分开捕获。

只需使用out!

结束通信...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接