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  
25  import org.apache.mina.filter.executor.ExecutorFilter;
26  
27  import edu.emory.mathcs.backport.java.util.concurrent.Executor;
28  import edu.emory.mathcs.backport.java.util.concurrent.ThreadFactory;
29  import edu.emory.mathcs.backport.java.util.concurrent.ThreadPoolExecutor;
30  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicInteger;
31  
32  /**
33   * A {@link ThreadModel} which represents a thread model with an {@link Executor}
34   * (from <a href="http://dcl.mathcs.emory.edu/util/backport-util-concurrent/">backport-util-concurrent</a>)
35   * per service.  The default underlying {@link Executor} is {@link ThreadPoolExecutor},
36   * so you can safely downcast the returned {@link Executor} of {@link #getExecutor()} to
37   * {@link ThreadPoolExecutor} by default.
38   * 
39   * @author The Apache Directory Project (mina-dev@directory.apache.org)
40   * @version $Rev: 555855 $, $Date: 2007-07-13 12:19:00 +0900 (금, 13  7월 2007) $
41   */
42  public class ExecutorThreadModel implements ThreadModel {
43      /**
44       * Maps a service name to a PooledThreadModel instance.
45       * Without this map, we might create extremely many thread pools that leads the system to
46       * coma. */
47      private static final Map service2model = new HashMap();
48  
49      /**
50       * Returns a {@link ExecutorThreadModel} instance for the specified <tt>serviceName</tt>.
51       * Please note that all returned instances will be managed globally; the same instance
52       * will be returned if you specified the same service name.  Please try to specify
53       * different names for different services.
54       * 
55       * @param serviceName the name of the service that needs thread pooling
56       */
57      public static ExecutorThreadModel getInstance(String serviceName) {
58          if (serviceName == null) {
59              throw new NullPointerException("serviceName");
60          }
61  
62          ExecutorThreadModel model;
63          synchronized (service2model) {
64              model = (ExecutorThreadModel) service2model.get(serviceName);
65              if (model == null) {
66                  model = new ExecutorThreadModel(serviceName);
67                  service2model.put(serviceName, model);
68              }
69          }
70  
71          return model;
72      }
73  
74      private final String threadNamePrefix;
75  
76      private final ExecutorFilter defaultFilter;
77  
78      private ExecutorFilter filter = new ExecutorFilter();
79  
80      private ExecutorThreadModel(String threadNamePrefix) {
81          this.threadNamePrefix = threadNamePrefix;
82  
83          // Create the default filter
84          defaultFilter = new ExecutorFilter();
85          ThreadPoolExecutor tpe = (ThreadPoolExecutor) defaultFilter
86                  .getExecutor();
87          final ThreadFactory originalThreadFactory = tpe.getThreadFactory();
88          ThreadFactory newThreadFactory = new ThreadFactory() {
89              private final AtomicInteger threadId = new AtomicInteger(0);
90  
91              public Thread newThread(Runnable runnable) {
92                  Thread t = originalThreadFactory.newThread(runnable);
93                  t.setName(ExecutorThreadModel.this.threadNamePrefix + '-'
94                          + threadId.incrementAndGet());
95                  t.setDaemon(true);
96                  return t;
97              }
98          };
99          tpe.setThreadFactory(newThreadFactory);
100 
101         // Set to default.
102         setExecutor(null);
103     }
104 
105     /**
106      * Returns the underlying {@link Executor} of this model.
107      * You can change various properties such as the number of threads
108      * by calling methods of the {@link Executor} implementation.
109      */
110     public Executor getExecutor() {
111         return filter.getExecutor();
112     }
113 
114     /**
115      * Changes the underlying {@link Executor} of this model.
116      * Previous settings such as the number of threads should be configured again.
117      * Only newly created {@link IoSession}s will be affected.
118      * 
119      * @param executor <tt>null</tt> to revert to the default setting
120      */
121     public void setExecutor(Executor executor) {
122         if (executor == null) {
123             filter = defaultFilter;
124         } else {
125             filter = new ExecutorFilter(executor);
126         }
127     }
128 
129     public void buildFilterChain(IoFilterChain chain) throws Exception {
130         chain.addFirst(ExecutorThreadModel.class.getName(), filter);
131     }
132 }