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 (Fri, 13 Jul 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 }