View Javadoc

    1   /*
    2    * Copyright 2012 The Netty Project
    3    *
    4    * The Netty Project licenses this file to you under the Apache License,
    5    * version 2.0 (the "License"); you may not use this file except in compliance
    6    * with the License. You may obtain a copy of the License at:
    7    *
    8    *   http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    13   * License for the specific language governing permissions and limitations
    14   * under the License.
    15   */
    16  package org.jboss.netty.channel.socket.oio;
    17
    18  import java.util.concurrent.Executor;
    19  import java.util.concurrent.Executors;
    20  import java.util.concurrent.RejectedExecutionException;
    21
    22  import org.jboss.netty.channel.Channel;
    23  import org.jboss.netty.channel.ChannelPipeline;
    24  import org.jboss.netty.channel.group.ChannelGroup;
    25  import org.jboss.netty.channel.socket.DatagramChannel;
    26  import org.jboss.netty.channel.socket.DatagramChannelFactory;
    27  import org.jboss.netty.util.internal.ExecutorUtil;
    28
    29  /**
    30   * A {@link DatagramChannelFactory} which creates a blocking I/O based
    31   * {@link DatagramChannel}.  It utilizes the good old blocking I/O API which
    32   * has support for multicast.
    33   *
    34   * <h3>How threads work</h3>
    35   * <p>
    36   * There is only one type of threads in {@link OioDatagramChannelFactory};
    37   * worker threads.
    38   *
    39   * <h4>Worker threads</h4>
    40   * <p>
    41   * Each {@link Channel} has a dedicated worker thread, just like a
    42   * traditional blocking I/O thread model.
    43   *
    44   * <h3>Life cycle of threads and graceful shutdown</h3>
    45   * <p>
    46   * Worker threads are acquired from the {@link Executor} which was specified
    47   * when a {@link OioDatagramChannelFactory} was created (i.e. {@code workerExecutor}.)
    48   * Therefore, you should make sure the specified {@link Executor} is able to
    49   * lend the sufficient number of threads.
    50   * <p>
    51   * Worker threads are acquired lazily, and then released when there's nothing
    52   * left to process.  All the related resources are also released when the
    53   * worker threads are released.  Therefore, to shut down a service gracefully,
    54   * you should do the following:
    55   *
    56   * <ol>
    57   * <li>close all channels created by the factory usually using
    58   *     {@link ChannelGroup#close()}, and</li>
    59   * <li>call {@link #releaseExternalResources()}.</li>
    60   * </ol>
    61   *
    62   * Please make sure not to shut down the executor until all channels are
    63   * closed.  Otherwise, you will end up with a {@link RejectedExecutionException}
    64   * and the related resources might not be released properly.
    65   *
    66   * <h3>Limitation</h3>
    67   * <p>
    68   * A {@link DatagramChannel} created by this factory does not support asynchronous
    69   * operations.  Any I/O requests such as {@code "write"} will be performed in a
    70   * blocking manner.
    71   *
    72   * @apiviz.landmark
    73   */
    74  public class OioDatagramChannelFactory implements DatagramChannelFactory {
    75
    76      private final Executor workerExecutor;
    77      final OioDatagramPipelineSink sink;
    78
    79      /**
    80       * Creates a new instance with a {@link Executors#newCachedThreadPool()}
    81       *
    82       * See {@link #OioDatagramChannelFactory(Executor)}
    83       */
    84      public OioDatagramChannelFactory() {
    85          this(Executors.newCachedThreadPool());
    86      }
    87
    88      /**
    89       * Creates a new instance.
    90       *
    91       * @param workerExecutor
    92       *        the {@link Executor} which will execute the I/O worker threads
    93       */
    94      public OioDatagramChannelFactory(Executor workerExecutor) {
    95          if (workerExecutor == null) {
    96              throw new NullPointerException("workerExecutor");
    97          }
    98          this.workerExecutor = workerExecutor;
    99          sink = new OioDatagramPipelineSink(workerExecutor);
    100     }
    101
    102     public DatagramChannel newChannel(ChannelPipeline pipeline) {
    103         return new OioDatagramChannel(this, pipeline, sink);
    104     }
    105
    106     public void releaseExternalResources() {
    107         ExecutorUtil.terminate(workerExecutor);
    108     }
    109 }