Thread.yield 是否与 Java 中的非阻塞 IO 相同

Is Thread.yield same as non blocking IO in Java

我知道非阻塞 IO 不会阻塞调用线程,而是在等待 IO 时释放它去做其他事情。

我刚刚了解了 Thread. yield 方法,该方法允许线程将 CPU 告知 运行 其他线程...技术上产生控制。

这两个东西,非阻塞 IO 和 Thread. yield 听起来和我很相似,所以我想知道,在最基本的层面上,非阻塞 IO 只是 Thread. yield 在什么时候投入使用做 IO?

TL;DR: 不,Thread.yield() 不能也不应该用于 任何事情

机制看似相似,但yield()与非阻塞IO无关,也不能用于实现非阻塞IO。这也很麻烦,行为取决于平台,因此应该 not be used.

虽然阻塞 IO 的工作原理是让一个线程在输入流上“锁定自身”并在输入到达时唤醒,但非阻塞 IO 却相反,并且有一个中央 selector(一种本机机制)可以获取输入数据可用时通知。它可以同时观察数千个通道,并在不需要任何关注的通道上花费零资源。当数据在通道上可用时,选择器会将数据定向到工作线程进行处理。它很高效,但也不同于阻塞 IO,而且更复杂。

因为yield()只告诉CPU“我没有工作要做,在我休息的时候随意运行其他线程”,它仍然以同样的方式工作作为常规 IO。你要避开无事可做的线程,yield就是主动什么都不做,而不是让调度器来决定。

现在你可能认为你可以编写类似下面的东西来模拟非阻塞 IO

List<InputStream> ins ...
while(true) {
    for(InputStream in : ins) {
        if(in.available() > 0) {
            int input = in.read();
            // do something with input
        }
    }
    Thread.yield();
}

您可能认为代码就像一个选择器。遍历阻塞的输入流,检查它们是否有数据要读取,如果有,读取数据并处理它,并可能在循环后产生线程以进行良好测量。

上面的代码有缺陷主要是因为调用了InputStream.available()。它可以用来判断如果呼叫 return 是正数,则呼叫何时 不会 阻塞,但它可以 return 0 并且仍然不会阻塞.您可能(并且很可能会)最终永远循环遍历这些流而不读取任何内容,因为逻辑认为它会阻塞因为 available() returns 0 只是因为它不能 确定 它不会阻塞。这是阻塞和非阻塞 IO 之间的主要区别。知道读取是否会被 BIO 阻塞的唯一可靠方法是调用 read()。然后你可能会被卡住。

这是斯蒂芬对 available() in socket programming 问题的很好解释。