Finlay Weber
Finlay Weber

Reputation: 4163

Is Thread.yield same as non blocking IO in Java

I know that non-blocking IO do not block on the calling thread but releases it to do other things while awaiting the IO.

I just learned about Thread. yield method which allows a thread to tell the CPU to run other threads...technically yielding control.

These two things, non-blocking IO and Thread. yield sounds similar to me, so I was wondering, at the most fundamental level, are non-blocking IO just Thread. yield put to use when doing IO?

Upvotes: 3

Views: 661

Answers (1)

Kayaman
Kayaman

Reputation: 73568

TL;DR: No, Thread.yield() can't and shouldn't be used for anything.

The mechanism may seem similar, but yield() is not related to and cannot be used to implement non-blocking IO. It's also cumbersome, behaviour is platform dependent, and therefore should not be used.

While blocking IO works by having a thread "lock itself" on an input stream and wake up when input arrives, non-blocking IO reverses this and there's a central selector (a native mechanism) that gets notified when input data is available. It can observe thousands of channels at the same time, and spend zero resources on those that don't require any attention. When data is available on a channel, the selector then directs that data to a worker thread to process. It's efficient, but also different and more complicated than blocking IO.

Since yield() only tells the CPU that "I have no work to do, feel free to run other threads while I rest", it's still working in the same way as regular IO. You want to avoid threads that don't have anything to do, and yielding is just actively not doing anything, instead of letting the scheduler determine it.

Now you might think you could write something like the following to simulate non-blocking IO

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

You might think that the code acts like a selector. Going through the blocking input streams, checking if they have data to read, if so, reading the data and processing it, and maybe yielding the thread after the loop for good measure.

The above code is flawed mainly because of the call to InputStream.available(). It can be used to tell when a call will not block if it returns a positive number, but it can return 0 and still not block. You might (and very possibly will) end up looping over those streams forever and not read anything because the logic thinks it will block because available() returns 0 just because it cannot be sure that it won't block. This is the major difference between blocking and non-blocking IO. The only sure way to know if a read will block with BIO, is to call read(). And then you might be stuck.

Here's Stephen's good explanation of problems with available() in socket programming.

Upvotes: 5

Related Questions