001/*
002 * $Id$
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();
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            pool = Executors.newCachedThreadPool();
118        }
119        //System.out.println("pool_init = " + pool);
120        return pool;
121        //return Executors.unconfigurableExecutorService(pool);
122
123        /* not useful, is not run from jython
124        Runtime.getRuntime().addShutdownHook( );
125        */
126    }
127
128
129    /**
130     * Stop execution.
131     */
132    public static synchronized void terminate() {
133        if (pool == null) {
134            return;
135        }
136        if (pool instanceof ThreadPoolExecutor) {
137            ThreadPoolExecutor tpe = (ThreadPoolExecutor) pool;
138            //logger.info("task queue size         {}", Q_CAPACITY);
139            logger.info("number of CPUs            {}", N_CPUS);
140            logger.info("core number of threads    {}", N_THREADS);
141            logger.info("current number of threads {}", tpe.getPoolSize());
142            logger.info("maximal number of threads {}", tpe.getLargestPoolSize());
143            BlockingQueue<Runnable> workpile = tpe.getQueue();
144            if (workpile != null) {
145                logger.info("queued tasks              {}", workpile.size());
146            }
147            List<Runnable> r = tpe.shutdownNow();
148            if (r.size() != 0) {
149                logger.info("unfinished tasks          {}", r.size());
150            }
151            logger.info("number of scheduled tasks  {}", tpe.getTaskCount());
152            logger.info("number of completed tasks {}", tpe.getCompletedTaskCount());
153        }
154        pool = null;
155        //workpile = null;
156    }
157
158
159    /**
160     * Set no thread usage.
161     */
162    public static synchronized void setNoThreads() {
163        NO_THREADS = true;
164    }
165
166
167    /**
168     * Set thread usage.
169     */
170    public static synchronized void setThreads() {
171        NO_THREADS = false;
172    }
173
174
175    /**
176     * Set timeout.
177     * @param t time value to set
178     */
179    public static synchronized void setTimeout(long t) {
180        timeout = t;
181    }
182
183
184    /**
185     * Get timeout.
186     * @return timeout value
187     */
188    public static synchronized long getTimeout() {
189        return timeout;
190    }
191
192
193    /**
194     * Set TimeUnit.
195     * @param t TimeUnit value to set
196     */
197    public static synchronized void setTimeUnit(TimeUnit t) {
198        timeunit = t;
199    }
200
201
202    /**
203     * Get TimeUnit.
204     * @return timeunit value
205     */
206    public static synchronized TimeUnit getTimeUnit() {
207        return timeunit;
208    }
209
210}