1 /*
2 * Copyright 2008 Ange Optimization ApS
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * 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 agreeds to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 /**
17 * @author Kim Hansen
18 */
19 package eu.simuline.octave.util;
20
21 import eu.simuline.octave.exec.OctaveExec;
22
23 import java.util.concurrent.ThreadFactory;
24 import java.util.concurrent.atomic.AtomicInteger;
25
26 /**
27 * A ThreadFactory that allows to create a thread from a runnable
28 * with a specific thread name.
29 *
30 * @author Kim Hansen
31 */
32 public final class NamedThreadFactory implements ThreadFactory {
33
34 /**
35 * This is initialized with 1
36 * and read and incremented only if a factory object is created.
37 * It goes into {@link #namePrefix}.
38 */
39 private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
40
41 /**
42 * The thread group from the security manager if it exists
43 * or else from the current thread.
44 * It is the group each thread belongs to created by {@link #newThread(Runnable)}.
45 */
46 private final ThreadGroup group;
47
48 /**
49 * The name prefix of the form
50 * <code><threadname>-javaoctave-<prefix>-<POOLNUMBER>-</code>,
51 * where <code><threadname></code> is the name of the current thread,
52 * <code><prefix></code> is the prefix given by a parameter
53 * of the constructor {@link #NamedThreadFactory(String)}
54 * and <code><POOLNUMBER></code> is {@link #POOL_NUMBER}
55 * depending on the factory object.
56 * The trailing <code>-</code> is there because a new thread
57 * defined by {@link #newThread(Runnable)} obtains a name
58 * consisting of the prefix followed by {@link #threadNumber}.
59 */
60 private final String namePrefix;
61
62 /**
63 * The number of the thread created next by this factory starting with one
64 * and being incremented by method {@link #newThread(Runnable)}.
65 *
66 */
67 private final AtomicInteger threadNumber = new AtomicInteger(1);
68
69 /**
70 * Will create a factory that create Threads with the names:
71 * <code>[parent]-javaoctave-[prefix]-[pool#]-[thread#]</code>.
72 * Here, <code>[parent]</code> is the name of the parent thread,
73 * i.e. of the current thread,
74 * <code>[prefix]</code> is given by the parameter
75 * <code>[pool#]</code> is the number of this factory
76 * and <code>[thread#]</code> refers to the number of the thread
77 * created by this factory.
78 *
79 * @param prefix
80 */
81 @SuppressWarnings("PMD.AvoidThreadGroup")
82 // Thread.getThreadGroup() causes warning
83 // only because threadgroup has methods which are not threadsafe.
84 // but we do not invoke method on group,
85 // use just to create new thread with that group.
86 private NamedThreadFactory(final String prefix) {
87 final SecurityManager securityManager = System.getSecurityManager();
88 this.group = (securityManager == null)
89 ? Thread.currentThread().getThreadGroup()
90 : securityManager .getThreadGroup();
91 this.namePrefix = Thread.currentThread().getName() + "-javaoctave-"
92 + prefix + "-" + POOL_NUMBER.getAndIncrement() + "-";
93 }
94
95 /**
96 * Creates a NamedThreadFactory via {@link #NamedThreadFactory(String)}
97 * with name given by the simple class name of {@link OctaveExec}.
98 */
99 public NamedThreadFactory() {
100 this(OctaveExec.class.getSimpleName());
101 }
102
103 /**
104 * Returns a new thread with standard priority which is no daemon
105 * with default priority {@link Thread#NORM_PRIORITY}
106 * from <code>runnable</code>
107 * with name consisting of {@link #namePrefix} and a running number
108 * {@link #threadNumber}.
109 *
110 * @param runnable
111 * the runnable to create a thread from.
112 */
113 @Override
114 public Thread newThread(final Runnable runnable) {
115 String name = this.namePrefix + this.threadNumber.getAndIncrement();
116 final Thread thread = new Thread(this.group, runnable, name);
117 if (thread.isDaemon()) {
118 // is a daemon iff this thread is a daemon
119 thread.setDaemon(false);
120 }
121 // Here, thread is no daemon
122 if (thread.getPriority() != Thread.NORM_PRIORITY) {
123 thread.setPriority(Thread.NORM_PRIORITY);
124 }
125 // Here, thread has NORM_PRIORITY
126 return thread;
127 }
128
129 }