没有执行单个指令就可以退出RUNNABLE状态吗?

时间:2015-07-07 16:47:57

标签: java multithreading

我正在阅读这本书Oracle Certified Professional Java SE 7 Programmer Exams 1Z0-804 and 1Z0-805。其中一个问题是询问此代码的输出

class ThreadTest {
    public static void main(String []args) throws InterruptedException {
        Thread t1 = new Thread() {
            public void run() { System.out.print("t1 "); }
        };
        Thread t2 = new Thread() {
            public void run() { System.out.print("t2 "); }
        };
        t1.start();
        t1.sleep(5000);
        t2.start();
        t2.sleep(5000);
        System.out.println("main ");
    }
}

该书说它始终会输出t1 t2 main,因为TIMED_WAITING州只能从RUNNABLE州到达。

但我认为线程可以在没有执行单个指令的情况下退出RUNNABLE状态。

医生说:

  

处于可运行状态的线程正在Java虚拟机中执行,但它可能正在等待来自操作系统的其他资源,例如处理器。

这本书的答案是否正确?并且可以在没有执行单个指令的情况下退出RUNNABLE状态吗?

1 个答案:

答案 0 :(得分:5)

我不相信这本书是正确的,但出于不同的原因。

首先,让我们直接处理您的问题。更改退出RUNNABLE状态的唯一方法是执行导致其状态发生变化的指令。该指令可能调用一个方法(恰好是同步的,然后线程等待BLOCKED中的锁定)或从run()方法返回(导致线程变为TERMINATED)。但是这些状态变化总是发生,因为线程已经做了一些事情来改变它自己的状态。

修改 - 只是为了详细说明;方法public void run() {}恰好包含一条指令:return。线程必须执行return才能从RUNNABLE到TERMINATED。

这本书是错的(有点)。在正常情况下" 5秒很容易就足以启动一个线程。但没有任何东西可以同步线程,因此没有任何东西强迫线程以任何特定的顺序执行任务。

流程是:

  1. 主线程启动t1。
  2. 然后主线程进入睡眠状态5秒钟。 你希望5秒足以让操作系统启动一个线程,但不能保证它会。如果操作系统当前受到fork bomb的攻击,则可能没有资源来启动新线程。
  3. 主线程然后开始t2。 如果操作系统全部堵塞并且t1尚未启动,则无法保证t2不会首先启动(执行某些代码)。
  4. 然后主线程进入睡眠状态5秒钟。
  5. 然后主线程打印"main "。再次,如果操作系统被堵塞,这可能实际上发生在t1或t2开始之前。
  6. 不使用同步就不要依赖多个线程的序列!