【问题标题】:Java - System.exit() and scannerJava - System.exit() 和扫描仪
【发布时间】:2017-10-25 09:09:24
【问题描述】:

假设我打开了一个扫描仪,无论是来自System.in 还是来自文件,并且在程序中的某个时刻我正在激活System.exit(),(并且之前没有调用scanner.close()),它如何(以及是否)影响扫描仪?

我在想,自从system.exit() 方法关闭了 JVM,与扫描器相关的所有东西都将被正确关闭,但我没有找到关于这种情况的任何具体信息。例如 - 在System.exit() 之后,扫描仪打开的文件是否会被解锁(从扫描仪中“释放”)?在scanner.close() 激活的所有相关进程是否也会被System.exit()“激活”?

【问题讨论】:

    标签: java java.util.scanner system.exit


    【解决方案1】:

    扫描仪是一个流,所以当程序终止时,流会自动为您关闭,但是不关闭流是不好的做法,因为在较大的运行时间较长的程序中它们可能会导致问题,所以是的,一切都会正常关闭,但正如所说早一点是不好的做法。

    如果您一次打开多个流,它会因 outOfMemoryError 而崩溃,这是一个示例

    public static void main(String[] args) {
    LinkedList<Scanner> list = new LinkedList<>();
    while(true)
        list.add(new Scanner(System.in));
    }
    

    所以如果你长时间不关闭你的流,就会导致这个内存错误,还要注意这个错误不是因为列表中的项目太多而是因为流引起的

    编辑:

    public static void main(String[] args) {
        Scanner first = new Scanner(System.in);
        Scanner second = new Scanner(System.in);
        int x = first.nextInt();
        int y = second.nextInt();
        System.out.println("First scan returns: " + x);
        System.out.println("Second scan returns: " + y);
        first.close();
        second.close();
    }
    

    如您所见,您可以打开多个 System.in 扫描器,但是在读取变量时,您必须指定要使用的扫描器对象。然而,这当然是没有意义的,我想不出为什么你需要一次打开多个 System.in 扫描仪。

    【讨论】:

    • 那么扫描仪打开的所有文件都会在system.exit()处关闭?你能举一个在大型程序中可能发生的可选问题的例子吗?
    • @Mickey 是的,所有打开的文件和流都将被关闭,就像您调用 close 方法一样,现在大型程序中可能发生的问题将是 OutOfMemoryError,因为您一次只能打开这么多 Steam,因此对于大多数程序,即使是大型程序,也需要一段时间才能达到此限制,但如果您有需要长时间运行的服务器或程序,这可能会导致它崩溃。
    • 谢谢。对于您在评论中编辑的示例,是否可以打开多个system.in 扫描仪?据我所知,你不能。另外,OutOfMemoryError 是如何连接到System.exit() 部分的?我不太明白。
    • @Mickey 是的,可以打开多个 System.in 扫描仪,但是您必须指定在读取输入时要使用哪一个,我将在上述答案的示例中进行编辑
    • System.exit() 是一种可接受的退出程序的方式,但它实际上取决于程序应该做什么,如果你有一个程序可以进行一些计算,你就不需要使用 System .exit(),因为一旦完成程序会自行退出,但是假设你有一个游戏,游戏不知道用户将程序打开多长时间,所以它需要在用户调用 System.exit()单击退出按钮退出。但是,一旦程序退出,它是否崩溃、正常退出或调用 System.exit() 都无关紧要,所有流都会自动为您关闭。
    【解决方案2】:

    我会这样回答你的问题。运行 java 进程的操作系统是一个编写良好且经过无限测试的软件。当一个进程退出(比如一个java进程)时,操作系统会:

    • 使 java 进程使用的内存 (RAM) 可用,即释放内存。
    • java 进程持有的文件描述符被清除。这将包括它正在读取或写入的任何文件等。
    • 等等。

    但这并不意味着 Java 流程不遵循最佳实践。让我举个例子:想象一下java进程有两个线程在运行——其中一个正在更新文件,另一个调用exit。该文件可能已损坏。因此,如果调用此方法,最佳实践要求对关闭挂钩进行编程以处理此类情况。这些钩子应该尝试关闭资源并执行其他类型的内务处理。

    也许这会有所帮助:一旦 System.exit() 被调用,那么继续执行的代码将不会被执行。所以如果你有一个scanner.close(),除非它在关闭钩子中,否则它不会被执行。当然,操作系统会在进程退出时释放文件描述符。

    【讨论】:

    • 这并不是一个很好的例子,因为在一个完全单线程的程序中文件可能会以这种方式“损坏”,该程序会关闭所有内容,具有退出钩子等。
    • 我只是举了一个例子,说明如果不遵循最佳实践可能会发生什么。从来没有说过这是文件损坏的唯一方法。 :-)
    • 这并不能真正说明为什么这些是“最佳实践”,因为它们实际上并没有阻止您声称他们阻止的事情。
    • 我不同意,因为关闭挂钩是最佳做法。我休息一下。
    • '这是一个最佳实践,因为它是一个最佳实践,我相信我的情况'是强有力的非论据。
    猜你喜欢
    • 2013-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-03
    相关资源
    最近更新 更多