View Javadoc

    1   /*
    2    * Copyright 2009 Red Hat, Inc.
    3    *
    4    * Red Hat licenses this file to you under the Apache License, version 2.0
    5    * (the "License"); you may not use this file except in compliance with the
    6    * 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.RejectedExecutionException;
    20
    21  import org.jboss.netty.channel.Channel;
    22  import org.jboss.netty.channel.ChannelPipeline;
    23  import org.jboss.netty.channel.ChannelSink;
    24  import org.jboss.netty.channel.group.ChannelGroup;
    25  import org.jboss.netty.channel.socket.ServerSocketChannel;
    26  import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
    27  import org.jboss.netty.util.internal.ExecutorUtil;
    28
    29  /**
    30   * A {@link ServerSocketChannelFactory} which creates a server-side blocking
    31   * I/O based {@link ServerSocketChannel}.  It utilizes the good old blocking
    32   * I/O API which is known to yield better throughput and latency when there
    33   * are relatively small number of connections to serve.
    34   *
    35   * <h3>How threads work</h3>
    36   * <p>
    37   * There are two types of threads in a {@link OioServerSocketChannelFactory};
    38   * one is boss thread and the other is worker thread.
    39   *
    40   * <h4>Boss threads</h4>
    41   * <p>
    42   * Each bound {@link ServerSocketChannel} has its own boss thread.
    43   * For example, if you opened two server ports such as 80 and 443, you will
    44   * have two boss threads.  A boss thread accepts incoming connections until
    45   * the port is unbound.  Once a connection is accepted successfully, the boss
    46   * thread passes the accepted {@link Channel} to one of the worker
    47   * threads that the {@link OioServerSocketChannelFactory} manages.
    48   *
    49   * <h4>Worker threads</h4>
    50   * <p>
    51   * Each connected {@link Channel} has a dedicated worker thread, just like a
    52   * traditional blocking I/O thread model.
    53   *
    54   * <h3>Life cycle of threads and graceful shutdown</h3>
    55   * <p>
    56   * All threads are acquired from the {@link Executor}s which were specified
    57   * when a {@link OioServerSocketChannelFactory} was created.  Boss threads are
    58   * acquired from the {@code bossExecutor}, and worker threads are acquired from
    59   * the {@code workerExecutor}.  Therefore, you should make sure the specified
    60   * {@link Executor}s are able to lend the sufficient number of threads.
    61   * <p>
    62   * Both boss and worker threads are acquired lazily, and then released when
    63   * there's nothing left to process.  All the related resources are also
    64   * released when the boss and worker threads are released.  Therefore, to shut
    65   * down a service gracefully, you should do the following:
    66   *
    67   * <ol>
    68   * <li>unbind all channels created by the factory,
    69   * <li>close all child channels accepted by the unbound channels,
    70   *     (these two steps so far is usually done using {@link ChannelGroup#close()})</li>
    71   * <li>call {@link #releaseExternalResources()}.</li>
    72   * </ol>
    73   *
    74   * Please make sure not to shut down the executor until all channels are
    75   * closed.  Otherwise, you will end up with a {@link RejectedExecutionException}
    76   * and the related resources might not be released properly.
    77   *
    78   * <h3>Limitation</h3>
    79   * <p>
    80   * A {@link ServerSocketChannel} created by this factory and its child channels
    81   * do not support asynchronous operations.  Any I/O requests such as
    82   * {@code "write"} will be performed in a blocking manner.
    83   *
    84   * @author <a href="http://www.jboss.org/netty/">The Netty Project</a>
    85   * @author <a href="http://gleamynode.net/">Trustin Lee</a>
    86   *
    87   * @version $Rev: 2080 $, $Date: 2010-01-26 18:04:19 +0900 (Tue, 26 Jan 2010) $
    88   *
    89   * @apiviz.landmark
    90   */
    91  public class OioServerSocketChannelFactory implements ServerSocketChannelFactory {
    92
    93      final Executor bossExecutor;
    94      private final Executor workerExecutor;
    95      private final ChannelSink sink;
    96
    97      /**
    98       * Creates a new instance.
    99       *
    100      * @param bossExecutor
    101      *        the {@link Executor} which will execute the boss threads
    102      * @param workerExecutor
    103      *        the {@link Executor} which will execute the I/O worker threads
    104      */
    105     public OioServerSocketChannelFactory(
    106             Executor bossExecutor, Executor workerExecutor) {
    107         if (bossExecutor == null) {
    108             throw new NullPointerException("bossExecutor");
    109         }
    110         if (workerExecutor == null) {
    111             throw new NullPointerException("workerExecutor");
    112         }
    113         this.bossExecutor = bossExecutor;
    114         this.workerExecutor = workerExecutor;
    115         sink = new OioServerSocketPipelineSink(workerExecutor);
    116     }
    117
    118     public ServerSocketChannel newChannel(ChannelPipeline pipeline) {
    119         return new OioServerSocketChannel(this, pipeline, sink);
    120     }
    121
    122     public void releaseExternalResources() {
    123         ExecutorUtil.terminate(bossExecutor, workerExecutor);
    124     }
    125 }