View Javadoc
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       */
38      private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
39  
40      /**
41       * The thread group either from the security manager 
42       * or from the current thread. 
43       */
44      private final ThreadGroup group;
45  
46      /**
47       * The name prefix of the form 
48       * <code>&lt;threadname>-javaoctave-&lt;prefix>-&lt;POOLNUMBER>-</code>, 
49       * where <code>&lt;threadname></code> is the name of the current thread, 
50       * <code>&lt;prefix></code> is the prefix given by a parameter 
51       * of the constructor {@link #NamedThreadFactory(String)} 
52       * and <code>&lt;POOLNUMBER></code> is {@link #POOL_NUMBER} 
53       * depending on the factory object. 
54       * The trailing <code>-</code> is there because a new thread 
55       * defined by {@link #newThread(Runnable)} obtains a name 
56       * consisting of the prefix followed by {@link #threadNumber}. 
57       */
58      private final String namePrefix;
59  
60      /**
61       * The number of the thread created next by this factory starting with one 
62       * and being incremented by method {@link #newThread(Runnable)}. 
63       * 
64       */
65      private final AtomicInteger threadNumber = new AtomicInteger(1);
66  
67      /**
68       * Will create a factory that create Threads with the names: 
69       * <code>[parent]-javaoctave-[prefix]-[pool#]-[thread#]</code>. 
70       * Here, <code>[parent]</code> is the name of the parent thread, 
71       * i.e. of the current thread, 
72       * <code>[prefix]</code> is given by the parameter 
73       * <code>[pool#]</code> is the number of this factory 
74       * and <code>[thread#]</code> refers to the number of the thread 
75       * created by this factory. 
76       * 
77       * @param prefix
78       */
79      @SuppressWarnings("PMD.AvoidThreadGroup")
80      // Thread.getThreadGroup() causes warning 
81      // only because threadgroup has methods which are not threadsafe. 
82      // but we do not invoke method on group, 
83      // use just to create new thread with that group. 
84      private NamedThreadFactory(final String prefix) {
85          final SecurityManager securityManager = System.getSecurityManager();
86          this.group = (securityManager == null) 
87  	    ? Thread.currentThread().getThreadGroup()
88  	    : securityManager       .getThreadGroup();
89          this.namePrefix = Thread.currentThread().getName() + "-javaoctave-" 
90  	    + prefix + "-" + POOL_NUMBER.getAndIncrement() + "-";
91      }
92  
93      public NamedThreadFactory() {
94  	this(OctaveExec.class.getSimpleName());
95      }
96  
97      /**
98       * Returns a new thread with standard priority which is no daemon 
99       * from <code>runnable</code> 
100      * with name consisting of {@link #namePrefix} and a running number 
101      * {@link #threadNumber}. 
102      *
103      * @param runnable
104      *    the runnable to create a thread from. 
105      */
106     @Override
107     public Thread newThread(final Runnable runnable) {
108 	String name = this.namePrefix + this.threadNumber.getAndIncrement();
109         final Thread thread = new Thread(this.group, runnable, name);
110         if (thread.isDaemon()) {
111             thread.setDaemon(false);
112         }
113 	// Here, thread is no daemon 
114         if (thread.getPriority() != Thread.NORM_PRIORITY) {
115             thread.setPriority(Thread.NORM_PRIORITY);
116         }
117 	// Here, thread has NORM_PRIORITY 
118         return thread;
119     }
120 
121 }