title: How to find and cancel idle channels of a selector?
body: <p>Let's say we have a Java NIO <code>Selector</code> that selects with a timeout on multiple <code>SocketChannels</code> for read operations:</p>
  
  <pre class="lang-java prettyprint-override"><code>Selector selector = Selector.open();
  channel1.register(selector, SelectionKey.OP_READ);
  channel2.register(selector, SelectionKey.OP_READ);
  channel3.register(selector, SelectionKey.OP_READ);
  channel4.register(selector, SelectionKey.OP_READ);
  // ... maybe even more ...
  
  while (true) {
      if (selector.select(TIMEOUT) &gt; 0) {
          Iterator&lt;SelectionKey&gt; iterator = selector.selectedKeys().iterator();
          while (iterator.hasNext()) {
              SelectionKey key = iterator.next();
              if (key.isValid() &amp;&amp; key.isReadable())
                  read(key);
              iterator.remove();
          }
      } else {
          // All channels timed-out! Cancel and close them all
          cancelAndCloseAll(selector.keys());
      }
  }
  </code></pre>
  
  <p><strong>We need to cancel and close a channel if it's been idle for a specific time,</strong> and that's why we're using the <code>selector.select(TIMEOUT)</code> method.</p>
  
  <p><strong>But this doesn't work if we have a few very active channels.</strong> Those active channels will never let the <code>select</code> to timeout, while all the other channels might be idle ...</p>
  
  <p><strong>A naive solution</strong> for this is as follows (also mentioned <a href="https://stackoverflow.com/questions/2661022/any-way-to-get-read-timeouts-with-java-nio-selectors">here</a>) :</p>
  
  <blockquote>
    <p>Attach the last time of activity to each channel's <code>SelectionKey</code> using the <code>key.attach(object)</code> method. After each successful select, update the activity time of all ready keys. Then iterate over all the keys and find the ones that have been idle more than the specific threshold.</p>
  </blockquote>
  
  <p>This could be really inefficient because the active channels will cause the <code>select</code> to fire very frequently and everytime iterating all over the keys set.</p>
  
  <p><strong>So is there a better (more efficient) way of solving this problem ?</strong></p>