2010-05-21 16 views
5

à l'aide d'un java.nio doit enregistrer un intérêt dans les opérations via le SelectableChannel:NIO Meilleures pratiques - SelectableChannel et InterestOps

SelectionKey = SelectableChannel.register(selector, interestInOpsBitmask) 

Intérêts Enregistrement:

  • SelectionKey existant écraser en exécutant SelectableChannel.register avec new Ops
  • VS. la mise à jour SelectionKey existant avec key.interestOps (key.interestOps() | newOp)

Intérêts désenregistrement:

  • SelectionKey.cancel et SelectableChannel.register avec de nouvelles opérations
  • VS. mettre à jour le SelectionKey existant comme ci-dessus

Y a-t-il des avantages & par contre?

Merci

Répondre

3

Si vous envoyez toujours l'exécution à un pool de threads après le retour de select(), vous souhaiterez peut-être annuler immédiatement la clé, puisque vous perdez le contrôle pendant la durée d'exécution du Runnable. Ex.: Si vous effectuez la sélection suivante() avant d'annuler la clé précédente (le thread est toujours en attente d'exécution), il sera encore valide, ce qui entraînera l'exécution par un autre thread de la clé déjà envoyée. Si l'un de ces threads annule la clé, l'autre obtiendra un CancelledKeyException en plus d'introduire un comportement inattendu.

Même si vous annulez la touche, un thread peut enregistrer le même canal (mettre à jour les touches de sélection) avant que le canal ne soit désenregistré (en raison de votre précédente key.cancel()). Que, encore une fois, provoquera un CancelledKeyException.

Pour se débarrasser de ce piège, vous pouvez gérer les événements toujours dans la boucle suivante:

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

exécution Firt sera, presque, jamais remettre les clés, mais le select() à la fin de votre loop MAY garantir que le canal de la touche annulée soit désenregistré (porter à votre discrétion) du sélecteur. Cependant, si vous exécutez simplement une tâche dans le même thread, vous écoutez vos événements de sélection, la mise à jour des sons est plus simple et plus sûre.

+0

vous pouvez modifier le délai d'attente de votre sélecteur s'il existe des tâches en cours d'exécution sur votre pool de threads.Si vous utilisez un gros timout dans select(), vous pouvez provoquer des threads bloqués pour l'enregistrement de canaux nouveaux/existants dans le sélecteur. – paulosuzart

3

je mettre à jour les interestOps existants à l'aide du ou opérateur comme vous le suggérez. Je serais préoccupé par les sélections manquantes si j'ai annulé (temporairement) la touche de sélection. De plus, cancel + reregister semble plus compliqué que la mise à jour.

Sauf si vous avez une raison logique sous-jacente pour vous inscrire avec de nouveaux ops, je suggère de toujours aller à la mise à jour.