Selector.wakeup()和"发生之前"关系

时间:2015-02-26 22:46:39

标签: java selector wakeup

我正在编写另一台NIO服务器。有一个选择器线程执行读取,处理(大多数情况下)和写入(下面的伪代码,而不是真正的Java):

while (true) {
    select();

    for (key : keys) {
        if (isReading(key)) {
            data = read(key.channel());

            result = process(data);

            key.interestOps(OP_WRITE);
        }

        if (isWriting(key)) {
            key.channel().write(result);
        }
    }
}

对大多数情况的处理是微不足道的,所以应该没问题。但是,有(罕见)情况,当处理非常耗时并且应该委托给另一个线程。因此,当处理完成时,该线程应以某种方式告诉选择器对OP_WRITE感兴趣。

我认为至少有两种方法可以做:

  1. 使用同步调用wakeup()和register()以在同一(工作线程)线程中写入,以防止发生下一个select()而不会导致register()挂起。
  2. 将“注册”操作排入队列,然后在工作线程中调用wakeup(),以允许选择器线程将操作队列化,以便在同一线程中注册写入。
  3. 我的问题是:如果我选择方法#2,是否必须使用线程安全的队列实现(例如,ConcurrentLinkedQueue)?我怀疑我不会因为enqueue()“before-before”dequeue()而被wakeup()调用保证,但我无法正式证明它。

    请帮忙!谢谢!

1 个答案:

答案 0 :(得分:1)

根据我的评论,你的问题是建立在一个谬误的基础上的。当处理完成时,您不需要告诉选择器对OP_WRITE感兴趣。您只需在创建响应时编写响应即可。只有在该写入返回零的情况下,才有必要使选择器对OP_WRITE感兴趣。

要回答您的补充问题,select()会参与三个记录的同步级别。 wakeup()没有,但您通常会跟随wakeup()跟随选择器上的同步块,您可以在其中使用选择器下次选择时需要了解的内容。这实现了所有必要的事先发生的关系。