View Javadoc

    1   /*
    2    *  Licensed to the Apache Software Foundation (ASF) under one
    3    *  or more contributor license agreements.  See the NOTICE file
    4    *  distributed with this work for additional information
    5    *  regarding copyright ownership.  The ASF licenses this file
    6    *  to you under the Apache License, Version 2.0 (the
    7    *  "License"); you may not use this file except in compliance
    8    *  with the License.  You may obtain a copy of the License at
    9    *
    10   *    http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   *  Unless required by applicable law or agreed to in writing,
    13   *  software distributed under the License is distributed on an
    14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15   *  KIND, either express or implied.  See the License for the
    16   *  specific language governing permissions and limitations
    17   *  under the License.
    18   *
    19   */
    20  package org.apache.mina.common;
    21
    22  import java.util.HashMap;
    23  import java.util.Map;
    24  import java.util.concurrent.Executor;
    25  import java.util.concurrent.ThreadFactory;
    26  import java.util.concurrent.ThreadPoolExecutor;
    27  import java.util.concurrent.atomic.AtomicInteger;
    28
    29  import org.apache.mina.filter.executor.ExecutorFilter;
    30  import org.apache.mina.util.NamePreservingRunnable;
    31
    32  /**
    33   * A {@link ThreadModel} which represents a thread model with an {@link Executor}
    34   * per service.  The default underlying {@link Executor} is {@link ThreadPoolExecutor},
    35   * so you can safely downcast the returned {@link Executor} of {@link #getExecutor()} to
    36   * {@link ThreadPoolExecutor} by default.
    37   *
    38   * @author The Apache Directory Project (mina-dev@directory.apache.org)
    39   * @version $Rev: 588150 $, $Date: 2007-10-25 15:20:04 +0900 (Thu, 25 Oct 2007) $
    40   */
    41  public class ExecutorThreadModel implements ThreadModel {
    42      /**
    43       * Maps a service name to a PooledThreadModel instance.
    44       * Without this map, we might create extremely many thread pools that leads the system to
    45       * coma. */
    46      private static final Map<String, ExecutorThreadModel> service2model = new HashMap<String, ExecutorThreadModel>();
    47
    48      /**
    49       * Returns a {@link ExecutorThreadModel} instance for the specified <tt>serviceName</tt>.
    50       * Please note that all returned instances will be managed globally; the same instance
    51       * will be returned if you specified the same service name.  Please try to specify
    52       * different names for different services.
    53       *
    54       * @param serviceName the name of the service that needs thread pooling
    55       */
    56      public static ExecutorThreadModel getInstance(String serviceName) {
    57          if (serviceName == null) {
    58              throw new NullPointerException("serviceName");
    59          }
    60
    61          ExecutorThreadModel model;
    62          synchronized (service2model) {
    63              model = service2model.get(serviceName);
    64              if (model == null) {
    65                  model = new ExecutorThreadModel(serviceName);
    66                  service2model.put(serviceName, model);
    67              }
    68          }
    69
    70          return model;
    71      }
    72
    73      private final String threadNamePrefix;
    74
    75      private final ExecutorFilter defaultFilter;
    76
    77      private ExecutorFilter filter = new ExecutorFilter();
    78
    79      private ExecutorThreadModel(String threadNamePrefix) {
    80          this.threadNamePrefix = threadNamePrefix;
    81
    82          // Create the default filter
    83          defaultFilter = new ExecutorFilter();
    84          ThreadPoolExecutor tpe = (ThreadPoolExecutor) defaultFilter
    85                  .getExecutor();
    86          final ThreadFactory originalThreadFactory = tpe.getThreadFactory();
    87          ThreadFactory newThreadFactory = new ThreadFactory() {
    88              private final AtomicInteger threadId = new AtomicInteger(0);
    89
    90              public Thread newThread(Runnable runnable) {
    91                  Thread t = originalThreadFactory.newThread(
    92                          new NamePreservingRunnable(
    93                                  runnable,
    94                                  ExecutorThreadModel.this.threadNamePrefix + '-' +
    95                                  threadId.incrementAndGet()));
    96                  t.setDaemon(true);
    97                  return t;
    98              }
    99          };
    100         tpe.setThreadFactory(newThreadFactory);
    101
    102         // Set to default.
    103         setExecutor(null);
    104     }
    105
    106     /**
    107      * Returns the underlying {@link Executor} of this model.
    108      * You can change various properties such as the number of threads
    109      * by calling methods of the {@link Executor} implementation.
    110      */
    111     public Executor getExecutor() {
    112         return filter.getExecutor();
    113     }
    114
    115     /**
    116      * Changes the underlying {@link Executor} of this model.
    117      * Previous settings such as the number of threads should be configured again.
    118      * Only newly created {@link IoSession}s will be affected.
    119      *
    120      * @param executor <tt>null</tt> to revert to the default setting
    121      */
    122     public void setExecutor(Executor executor) {
    123         if (executor == null) {
    124             filter = defaultFilter;
    125         } else {
    126             filter = new ExecutorFilter(executor);
    127         }
    128     }
    129
    130     public void buildFilterChain(IoFilterChain chain) throws Exception {
    131         chain.addFirst(ExecutorThreadModel.class.getName(), filter);
    132     }
    133 }