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