所以,如果我理解正确的话,当我们在一个对象上调用 wait 时,一个线程进入等待状态,当它等待一个对象上的锁时它进入阻塞状态(比如尝试进入同步块或方法时) )。
像 read() 这样的 I/O 方法是如何将线程置于阻塞状态的呢?我理解为什么它必须处于阻塞状态,等待它可以读取的数据,但我也对 HOW 感兴趣。当试图读取的资源中的数据再次可用时,JVM 如何通知线程它可以继续?
所以,如果我理解正确的话,当我们在一个对象上调用 wait 时,一个线程进入等待状态,当它等待一个对象上的锁时它进入阻塞状态(比如尝试进入同步块或方法时) )。
像 read() 这样的 I/O 方法是如何将线程置于阻塞状态的呢?我理解为什么它必须处于阻塞状态,等待它可以读取的数据,但我也对 HOW 感兴趣。当试图读取的资源中的数据再次可用时,JVM 如何通知线程它可以继续?
它不会将线程的状态更改为 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 不参与。
这取决于本机平台。
在 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
出现错误并且errno
is时循环EINTR
。
在 Windows 中,IO_Read
定义为handleRead
,它调用ReadFile
.