001/*
002 * $Id: ComputerThreads.java 5500 2016-05-12 21:29:42Z kredel $
003 */
004
005package edu.jas.kern;
006
007
008import java.util.List;
009import java.util.concurrent.BlockingQueue;
010import java.util.concurrent.ExecutorService;
011import java.util.concurrent.Executors;
012import java.util.concurrent.ThreadPoolExecutor;
013import java.util.concurrent.TimeUnit;
014
015import org.apache.log4j.Logger;
016
017
018/**
019 * ComputerThreads, provides global thread / executor service.
020 * @author Heinz Kredel
021 * @usage To obtain a reference to the thread pool use
022 *        <code>ComputerThreads.getPool()</code>. Once a pool has been created
023 *        it must be shutdown to exit JAS with
024 *        <code>ComputerThreads.terminate()</code>.
025 */
026
027public class ComputerThreads {
028
029
030    private static final Logger logger = Logger.getLogger(ComputerThreads.class);
031
032
033    // private static final boolean debug = logger.isInfoEnabled(); //logger.isInfoEnabled();
034
035
036    /**
037     * Flag for thread usage. <b>Note:</b> Only introduced because Google app
038     * engine does not support threads.
039     * @see edu.jas.ufd.GCDFactory#getProxy(edu.jas.structure.RingFactory)
040     */
041    public static boolean NO_THREADS = false;
042
043
044    /**
045     * Number of processors.
046     */
047    public static final int N_CPUS = Runtime.getRuntime().availableProcessors();
048
049
050    /*
051      * Core number of threads.
052      * N_CPUS x 1.5, x 2, x 2.5, min 3, ?.
053      */
054    public static final int N_THREADS = (N_CPUS < 3 ? 3 : N_CPUS + N_CPUS / 2);
055
056
057    //public static final int N_THREADS = ( N_CPUS < 3 ? 5 : 3*N_CPUS );
058
059
060    /**
061     * Timeout for timed execution. 
062     * @see edu.jas.fd.SGCDParallelProxy
063     */
064    static long timeout = 10L; //-1L;
065
066
067    /**
068     * TimeUnit for timed execution. 
069     * @see edu.jas.fd.SGCDParallelProxy
070     */
071    static TimeUnit timeunit = TimeUnit.SECONDS;
072
073
074    /*
075      * Saturation policy.
076      */
077    //public static final RejectedExecutionHandler REH = new ThreadPoolExecutor.CallerRunsPolicy();
078    //public static final RejectedExecutionHandler REH = new ThreadPoolExecutor.AbortPolicy();
079
080    /**
081     * ExecutorService thread pool.
082     */
083    //static ThreadPoolExecutor pool = null;
084    static ExecutorService pool = null;
085
086
087    /**
088     * No public constructor.
089     */
090    private ComputerThreads() {
091    }
092
093
094    /**
095     * Test if a pool is running.
096     * @return true if a thread pool has been started or is running, else false.
097     */
098    public static synchronized boolean isRunning() {
099        if (pool == null) {
100            return false;
101        }
102        if (pool.isTerminated() || pool.isShutdown()) {
103            return false;
104        }
105        return true;
106    }
107
108
109    /**
110     * Get the thread pool.
111     * @return pool ExecutorService.
112     */
113    public static synchronized ExecutorService getPool() {
114        if (pool == null) {
115            // workpile = new ArrayBlockingQueue<Runnable>(Q_CAPACITY);
116            //            pool = Executors.newFixedThreadPool(N_THREADS);
117            pool = Executors.newCachedThreadPool();
118            //             pool = new ThreadPoolExecutor(N_CPUS, N_THREADS,
119            //                                           100L, TimeUnit.MILLISECONDS,
120            //                                           workpile, REH);
121            //             pool = new ThreadPoolExecutor(N_CPUS, N_THREADS,
122            //                                           1000L, TimeUnit.MILLISECONDS,
123            //                                           workpile);
124        }
125        //System.out.println("pool_init = " + pool);
126        return pool;
127        //return Executors.unconfigurableExecutorService(pool);
128
129        /* not useful, is not run from jython
130        final GCDProxy<C> proxy = this;
131        Runtime.getRuntime().addShutdownHook( 
132                         new Thread() {
133                             public void run() {
134                                    logger.info("running shutdown hook");
135                                    proxy.terminate();
136                             }
137                         }
138        );
139        */
140    }
141
142
143    /**
144     * Stop execution.
145     */
146    public static synchronized void terminate() {
147        if (pool == null) {
148            return;
149        }
150        if (pool instanceof ThreadPoolExecutor) {
151            ThreadPoolExecutor tpe = (ThreadPoolExecutor) pool;
152            //logger.info("task queue size         " + Q_CAPACITY);
153            //logger.info("reject execution handler" + REH.getClass().getName());
154            logger.info("number of CPUs            " + N_CPUS);
155            logger.info("core number of threads    " + N_THREADS);
156            logger.info("current number of threads " + tpe.getPoolSize());
157            logger.info("maximal number of threads " + tpe.getLargestPoolSize());
158            BlockingQueue<Runnable> workpile = tpe.getQueue();
159            if (workpile != null) {
160                logger.info("queued tasks              " + workpile.size());
161            }
162            List<Runnable> r = tpe.shutdownNow();
163            if (r.size() != 0) {
164                logger.info("unfinished tasks          " + r.size());
165            }
166            logger.info("number of sheduled tasks  " + tpe.getTaskCount());
167            logger.info("number of completed tasks " + tpe.getCompletedTaskCount());
168        }
169        pool = null;
170        //workpile = null;
171    }
172
173
174    /**
175     * Set no thread usage.
176     */
177    public static synchronized void setNoThreads() {
178        NO_THREADS = true;
179    }
180
181
182    /**
183     * Set thread usage.
184     */
185    public static synchronized void setThreads() {
186        NO_THREADS = false;
187    }
188
189
190    /**
191     * Set timeout.
192     * @param t time value to set
193     */
194    public static synchronized void setTimeout(long t) {
195        timeout = t;
196    }
197
198
199    /**
200     * Get timeout.
201     * @return timeout value
202     */
203    public static synchronized long getTimeout() {
204        return timeout;
205    }
206
207
208    /**
209     * Set TimeUnit.
210     * @param t TimeUnit value to set
211     */
212    public static synchronized void setTimeUnit(TimeUnit t) {
213        timeunit = t;
214    }
215
216
217    /**
218     * Get TimeUnit.
219     * @return timeunit value
220     */
221    public static synchronized TimeUnit getTimeUnit() {
222        return timeunit;
223    }
224
225}