2

在下面的代码中,预测的输出可能是什么?

public class Threads2 implements Runnable {
    public void run() 
    {
        System.out.println("run.");
        throw new RuntimeException("Problem");
    }

    public static void main(String[] args) 
    {
        Thread t = new Thread(new Threads2());
        t.start();
        System.out.println("End of method.");
    }
}

作为答案给出的可能结果是:

End of method.
run.
java.lang.RuntimeException: Problem 

或者

run.
java.lang.RuntimeException: Problem 
End of method.

据我所知,只有第二个答案是可能的,请帮助我理解。

4

5 回答 5

3

两种答案都是可能的。由线程调度器决定何时执行并发线程的指令。启动的线程和主线程是“并行”运行的,唯一的保证是每个线程的指令都是按顺序执行的。但是这两个操作序列之间可能有任何交错。

顺便说一句,您还可以拥有以下内容。

run
end of method
java.lang.RuntimeException: Problem 

打个比方,假设你有一场跨栏比赛,你告诉每个跑步者开始比赛,一次一个。你知道哪个赛跑者会在每个障碍中获得第一名吗?不,你没有。这取决于每个跑步者的速度。如果第一个跑者起步很慢,最后一个跑者可能会在他面前的第一个障碍处出现。线程也是如此。调度程序将每个正在运行的线程分配给一个核心,按照他想要的任何顺序,以及它决定的任何时间。您拥有的唯一保证是每个线程都会执行一段时间。

于 2012-12-08T11:24:21.140 回答
2

t.start();告诉系统启动线程 - 没有说系统必须立即给线程执行时间。

另一种可能是:

run.
End of method.
java.lang.RuntimeException: Problem 
于 2012-12-08T11:25:31.657 回答
1

执行将产生两个线程,主线程(运行主方法的线程)和在主方法中创建的线程。由于您无法保证线程将运行的顺序,因此代码可以运行多个顺序。

所以让我们调用主线程 Thread1 和创建的线程 Thread2。然后,在 Thread2 启动后,可能性是:

  1. Thread1 首先获取处理器时间。(“方法结束......”首先打印)
  2. Thread2 首先获取处理器时间。(“运行”首先打印)

而且,实际上还有第三种可能性(我认为):

  1. Thread2 获取处理器时间并打印“运行”。
  2. Thread2 被中断,Thread1 接管。
  3. Thread1 打印“结束...”
  4. Thread2 抛出异常。
于 2012-12-08T11:28:05.443 回答
0

首先,请注意Exception的堆栈跟踪通常打印到stderr进程的流,而您写入stdout. 通常stderr被重定向到stdout,但这不是必需的。

要考虑的另一件事是文档没有说明任何关于并发访问的内容PrintStream#println(),因此当两个线程尝试同时打印时的输出确实是不可预测的。

鉴于在游戏中拥有异常堆栈跟踪没有多大意义(因为它完全是另一个流),所以问题减少到主线程和另一个线程之间先写入。这不仅取决于 JVM 调度程序,而且还考虑到该方法是不同步的,因此它甚至可以打印一个交错的字符串(好吧,我认为这在现实中不会发生,但这就是可能发生的情况) .

于 2012-12-08T11:29:22.470 回答
0

我认为您的问题是“为什么在打印异常后可以打印'run'的输出”。它们在同一个线程中,并且应该按顺序执行,这应该保证System.out.print("run");先执行然后再throw new RuntimeException("Problem");执行。

这里的问题是这两行代码使用了不同的打印队列。System.out.print()使用标准输出,而导致的错误信息throw new RuntimeException("Problem");将转到标准错误输出。因此,首先打印哪条消息不仅取决于首先执行哪一行代码,还取决于哪个输出队列首先刷新到屏幕。

如果第二行代码是,System.out.print("problem");则“问题”将始终在“运行”之后打印,因为它们使用相同的输出队列

于 2016-03-08T00:53:51.970 回答