2009-11-04 93 views
5

请在/两个线程之间给我提供一个selector.wakeup();方法的工作示例。java nio选择器唤醒

我试图创建一个简单的程序,其中一个线程正在等待selector.select()方法。第二个线程创建一些套接字并尝试向选择器注册;第一个线程被阻塞。

因此,我需要使用选择器的wakeup方法,但不知何故第一个线程不会出现阻塞模式。

唤醒方法状态的Javadoc:

如果另一线程当前在 Selector.select()或 Selector.select(长)方法的调用阻挡 然后 该调用将返回 立即。

P.S其他解决方法很少;其中之一是选择(超时),但我想弄清楚错误在哪里。

的伪代码:

第一线:

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 
     } 
    } 
} 

第二个线程:

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); 

} 

回答

4

你可能不希望有来自线程2插座如果你在选择器中注册它(因为选择器是用于非阻塞I/O的话)。我认为通常的做法是让选择器处理与OP_CONNECT的连接(使用SocketChannel.finishConnection())。

它也看起来像你可能在这里有潜在的竞争条件。想象一下这一系列事件:

  1. 主题1:selector.select()
  2. ...久而久之...
  3. 线程2:Thread1.selector.wakeup()
  4. 主题1:可接受性检查键
  5. 线程1:为了可读性检查键
  6. 线程1:环
  7. 线程1:selector.select()
  8. 线程2:尝试在选择注册(但一切都太迟了这个选择())

我建议有线程2建立了一个SocketChannel,藏匿它什么地方线程1罐(确保在执行此操作时确保线程安全),然后唤醒选择器,让它检查线程1中的现有密钥,并让线程1在再次调用Selector.select()之前注册新的SocketChannel。

+0

谢谢塞斯。连接到其他套接字是一种很少会发生的活动;因此我希望某种选择线程在每次选择键有活动时都不会检查某个集合/变量。 – Nilesh 2009-11-05 06:35:16