是线程.yield与Java中的非阻塞IO相同



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

我刚刚了解了Thread. yield方法,它允许一个线程告诉CPU运行其他线程…技术上控制产量

这两件事,非阻塞IO和Thread. yield听起来与我相似,所以我想知道,在最基本的层面上,非阻塞IO只是在做IO时使用Thread. yield吗?

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

机制可能看起来很相似,但yield()与非阻塞IO无关,也不能用于实现非阻塞IO。它也很麻烦,行为依赖于平台,因此不应该使用。

阻塞IO的工作原理是让线程"锁住自己"当输入流到达时唤醒,非阻塞IO逆转了这一点,并且有一个中央选择器(本机机制),当输入数据可用时得到通知。它可以同时观察数千个频道,并且在不需要任何关注的频道上花费零资源。当通道上有数据可用时,选择器将该数据定向到工作线程进行处理。这是有效的,但也不同,比阻塞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()。它可以用来判断调用何时将而不是。如果它返回一个正数,则阻塞,但它可以返回0而仍然不阻塞。你可能会(很可能会)在这些流上永远循环而没有读到任何东西因为逻辑认为它会阻塞因为available()返回0只是因为它不能确定它不会阻塞。这是阻塞和非阻塞IO之间的主要区别。知道一个读操作是否会被BIO阻塞的唯一可靠方法是调用read()。然后你可能会被卡住。

下面是Stephen对套接字编程中可用()的问题的很好的解释。

相关内容

最新更新