5

所以,如果我理解正确的话,当我们在一个对象上调用 wait 时,一个线程进入等待状态,当它等待一个对象上的锁时它进入阻塞状态(比如尝试进入同步块或方法时) )。

像 read() 这样的 I/O 方法是如何将线程置于阻塞状态的呢?我理解为什么它必须处于阻塞状态,等待它可以读取的数据,但我也对 HOW 感兴趣。当试图读取的资源中的数据再次可用时,JVM 如何通知线程它可以继续?

4

2 回答 2

7

它不会将线程的状态更改为 BLOCKED

public static void main(String[] args) throws IOException {
    Thread main = Thread.currentThread();
    new Thread(() -> {
        for (int i = 0; i < 10; i++) {
            System.out.println(main + " is in "+main.getState()+" state");
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                throw new AssertionError(e);
            }
        }
    }).start();
    System.in.read();
}

印刷

Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state
Thread[main,5,main] is in RUNNABLE state

相反,read直到有一些数据并且操作系统决定是否以及何时对线程/进程进行上下文切换,操作系统才会从那里返回。

当试图读取的资源中的数据再次可用时,JVM 如何通知线程它可以继续?

当有更多数据或流已关闭时,操作系统会唤醒线程。JVM 不参与。

于 2016-12-14T12:36:14.080 回答
0

这取决于本机平台。

在 POSIX 中,调用read通常会阻塞,直到数据可用,但还有许多其他返回原因,例如到达文件结尾、文件描述符已关闭、操作超时或信号中断操作。

在 Windows 中,最密切相关的功能是ReadFile.


血淋淋的细节,参考 Java 8 update 112 b15:

FileInputStream.read调用native FileInputStream.read0,通过Java_java_io_FileInputStream_read0中的JNI实现,它调用readSingle,它调用IO_Read

在 POSIX 中,IO_Read定义为handleRead,它调用read. 宏在RESTARTABLE出现错误并且errnois时循环EINTR

在 Windows 中,IO_Read定义为handleRead,它调用ReadFile.

于 2016-12-14T12:13:14.520 回答