Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java nio Selector wakeup

Tags:

java

nio

Please point/provide me an working example of selector.wakeup(); method between two threads.

I tried to create a simple program where a thread is waiting on selector.select() method. Second thread creates some sockets and tries to register with the selector; on which the first thread is blocked.

Hence I need to use selector's wakeup method, but somehow the first thread isnt doesn't come out of blocking mode.

The javadoc of wakeup method states:

If another thread is currently blocked in an invocation of the Selector.select() or Selector.select(long) methods then that invocation will return immediately.

P.S There are few other work-around; one of them is select(timeout) but I am trying to figure out where the mistake is.

The psuedo-code:

FIRST THREAD:

static Selector selector = Selector.open();
while(true) {
   int n = selectorGlobal.select();
   selectorKeySet = selectorGlobal.selectedKeys().iterator();
   while (selectorKeySet.hasNext()) {
      selectionKey = selectorKeySet.next();
      if (selectionKey.isReadable()) {
         //do something
      }
      if(selectionKey.isAcceptable()) {
         //accept
      }
   }
}

SECOND THREAD:

while (itr.hasNext()) { 
   data = (String) itr.next();
   String IP = data.get(0);
   String Port = data.get(1);

   SocketChannel socketChannel = SocketChannel.open();
   socketChannel.configureBlocking(true);
   boolean isConnected = socketChannel.connect(new InetSocketAddress(IP, Port));
   ClassName.selector.wakeup();
   SelectionKey selectionKey = SelectSockets.registerChannel(ClassName.selector,
                socketChannel, SelectionKey.OP_READ);

}
like image 534
Nilesh Avatar asked Nov 04 '09 15:11

Nilesh


1 Answers

You probably don't want to have the socket from Thread 2 be blocking if you're registering it in a selector (as selectors are meant for non-blocking I/O). I think it's also common practice to let the selector handle the connecting with OP_CONNECT (using SocketChannel.finishConnection()).

It also looks like you could have a potential race condition here. Imagine this series of events:

  1. Thread 1: selector.select()
  2. ... time passes ...
  3. Thread 2: Thread1.selector.wakeup()
  4. Thread 1: checks keys for acceptability
  5. Thread 1: checks keys for readibility
  6. Thread 1: loop
  7. Thread 1: selector.select()
  8. Thread 2: try to register in the selector (but it's too late for this select())

I'd suggest having Thread 2 set up a SocketChannel, stash it away somewhere Thread 1 can get at it (make sure to be thread safe when you do this), then wake up the selector, let it check it's existing keys in Thread 1 and have Thread 1 register the new SocketChannel before it calls Selector.select() again.

like image 142
Seth Avatar answered Oct 03 '22 02:10

Seth