2010-05-21 23 views
5

utilizando uno java.nio tiene que registrar su interés en las operaciones a través de la SelectableChannel:NIO Buenas Prácticas - SelectableChannel y InterestOps

SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask) 

Registro de Interés:

  • sobrescribir SelectionKey existente mediante la ejecución de SelectableChannel.register con nuevos Ops
  • VS. actualizar SelectionKey existente con key.interestOps (key.interestOps() | newOp)

interés anulación del registro:

  • SelectionKey.cancel y SelectableChannel.register con nuevos Operaciones
  • VS. actualizando la SelectionKey existente como la de arriba

¿Hay algún inconveniente &?

Gracias

Respuesta

3

Si siempre envía la ejecución a un grupo de subprocesos después de seleccionar() devolver, es posible que desee cancelar inmediatamente la clave, ya que pierde el control sobre el tiempo en que se ejecutará el ejecutable.

Ej .: Si realiza la siguiente selección() antes de cancelar la clave anterior (el hilo aún está esperando la ejecución), será válido aún, haciendo que otro hilo cargue la clave ya despachada. Si uno de estos subprocesos cancela la clave, el otro recibirá un CancelledKeyException además de presentar un comportamiento inesperado.

Incluso si cancela la clave, un hilo puede registrar el mismo canal (actualizar las teclas de selección) antes de que el canal no se registre (debido a su anterior key.cancel()). Lo que, de nuevo, causará una CancelledKeyException.

para deshacerse de esta trampa, es posible que desee controlar los eventos siempre en el siguiente bucle:

while (true) { // true or something less risky 
    //for each pendingTasks call 
    pool.execute(task); 
    Iterator<SelectionKey> iter = selector.selectedKeys().iterator(); 
    while (iter.hasNext()) { 
     SelectionKey key = iter.next(); 
     iter.remove(); 
     key.cancel(); 
     //store dispatch for the next while iteration 
     pendingTasks.add(task); // do not execute tasks before next select() 
    } 
    selector.select(TIMEOUT); // or selectNow if there are 
           //any pending events to handle. 
} 

ejecución Firt va, casi nunca volver llaves, pero la selección() al final de su loop MAY garantiza que el canal de la clave cancelada no se registre (cumpla con su impl) del selector.

Sin embargo, si simplemente está ejecutando una tarea en el mismo hilo, escuchará los eventos de su selector, actualizando los sonidos de forma más fácil y segura.

+0

cambiaría el tiempo de su selector si todavía hay tareas ejecutándose en su grupo de subprocesos.Si usa un gran timout en su select() puede causar hilos bloqueados para registrar canales nuevos/existentes en el selector. – paulosuzart

3

Me gustaría actualizar los interestOps existentes o mediante el operador como sugieres. Me preocuparía perder selecciones si cancelé (temporalmente) la clave de selección.

Además, cancelar + volver a registrar simplemente parece más complicado que la actualización.

A menos que tengas una razón lógica subyacente para registrarte con nuevas operaciones, te sugiero que siempre vayas con la actualización.

Cuestiones relacionadas