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