Non blocking IO - Programming model

2019-09-20 06:46发布

问题:

In non blocking IO programming model, a thread blocked on data available channels, as shown below,

in python,

while True:
    readers, _, _ = select.select([sys.stdin, sock], [], []) # blocked select()
    for reader in readers:
        if reader is sock:
            print(sock.recv(1000).decode('utf-8'))
        else:
            msg = sys.stdin.readline()
            sock.send(msg.encode('utf-8'))

in java,

     public void run() {
        while(true){
            try{
                executeCycle();
            } catch(IOException e){
                e.printStackTrace();
            }

            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }


    public void executeCycle() throws IOException {
        takeNewSockets();
        readFromSockets();
        writeToSockets();
    }

In Non-blocking IO programming model, execution flow generally follows the pattern of infinite-loop with the main(only) responsibility to find the data available channels(ready) and perform IO with the available channel.


In a scenario, where all channels are busy(for a duration), Does non-blocking IO programming model allow a thread that perform nio with/without infinite loop also to perform another CPU-bound task in same thread, for a meantime?

回答1:

These APIs usually allow you to specify a timeout for the selection step. That is, the amount of time to wait for any of the channels to be ready, returning an empty set if no channel became ready in the timeout. You can also do a non-block selection that returns immediately.

in python:

while True:
    readers, _, _ = select.select([sys.stdin, sock], [], [], 0) # non-block select
    # readers could be an empty list
    if readers:
        for reader in readers:
            if reader is sock:
                print(sock.recv(1000).decode('utf-8'))
            else:
                msg = sys.stdin.readline()
                sock.send(msg.encode('utf-8'))
    else:
        some_other_operations() # but only when no channel is ready

Java's Selector class has similar methods like selectNow() and select(long timeout) that you can use.



回答2:

I don't think it's easy to do the other operations in the same thread at the same time. You'd have to call the code to execute those other operations. How do you guarantee that control returns to checking the inputs in a reasonable timeframe?

But if you have a separate thread to handle other operations, then the runtime system will assign those threads to run whenever there are resources available. If you're using something like Thread.sleep(100) in the busy loop, then that will make sure this busy loop won't use up so many resources that other things will be able to run simultaneously without you having to do anything special.

You will have to make sure that any resources that are shared between the input checker thread and the other threads are handled in a threadsafe manner, however.