First of all, I’m not using selector.wakeup() or Thread.interrupt().
Selector.select() is supposed to block, until “at least one channel is selected”.
This behaviour is clearly breaking the contract defined in the Javadoc.
The thing I (might) do out of the ordinary, is that I keep changing the ‘interest ops’ of OP_WRITE, so that after the bytes are written, the OP_WRITE is not part of the interest ops anymore, and it gets activated again when i have data available.
All code is in the same Thread, so multi-threading issues are out of the question.
private LinkedList<byte[]> queue;
public void enqueue(SelectionKey key, byte[] buf)
{
queue.addLast(buf);
this.adjustInterestOps(key, OP_WRITE, true);
}
public void writeQueue(SelectionKey key)
{
if(queue.isEmpty())
{
this.adjustInterestOps(key, OP_WRITE, false);
return;
}
byte[] data = queue.removeFirst();
// write to SocketChannel
}
private final void adjustInterestOp(SelectionKey key, int op, boolean state)
{
try
{
int ops = key.interestOps();
if (state != ((ops & op) == op))
key.interestOps(state ? (ops | op) : (ops & ~op));
}
catch (CancelledKeyException exc)
{
// ignore
}
}
So what happens is that the code works perfectly fine, except that Selector.select() returns 0 quite often, which is pounding on my CPU (and again: breaking the contract of NIO). When there are events, like new clients, and read/write events, it works like normal, returning 1 or a value slightly higher.
I put a sleep(100) inthere now, if select() returns 0, but could anybody please explain to me why this code:
while(true)
{
int selected = selector.select();
System.out.println("selected: "+selected);
keys = selector.selectedKeys().iterator();
while (keys.hasNext())
{
SelectionKey key = keys.next();
keys.remove();
........
}
}
shows this behaviour:
selected: 1 // client connects
selected: 0
selected: 0
selected: 0
selected: 1 // client receives data
selected: 0
selected: 0
selected: 0
selected: 1 // client (ready to) write data
selected: 0
selected: 0
selected: 0
selected: 0
...
selected: 0
selected: 1 // client disconnects
// no more prints here... selector.select() now blocks after the last client disconnects