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