问题
I want to use the same thread pool throughout my application. To this end, I can make ExecutorService
static and global so that I can invoke ThreadUtil.executorService
to get ExecutorService
when I need it.
public class ThreadUtil {
public static final ExecutorService executorService = Executors.newCachedThreadPool();
}
Is it OK to instance multiple thread pools like this?
In addition, my application is a TCP server. If I don't know how big the pool should be, is it ok to simply use newCachedThreadPool
?
回答1:
When an instance with the same properties is to be used anywhere in your program, it is logical to declare it static and final instead of re-creating the instance each time but I would personally opt for a Singleton pattern instead of directly giving public access to the instance.
As for your second query, I don't see any problem with it. The first sentence of the documentation for newCachedThreadPool
says
Creates a thread pool that creates new threads as needed
since you don't know how many threads will be created, this is the most logical choice.
Note that newCachedThreadPool
will re-use old threads when they are available to increase performance.
回答2:
I would not make it directly global. At least wrap it in a class so you can easily use more than one pool. Having a pool of thread pool is very useful when you need more than one kind of job/ jobs with different priority. Just put fewer threads in the other pool and/or lower priority threads (by over riding the thread factory). For a sample can see https://github.com/tgkprog/ddt/tree/master/DdtUtils/src/main/java/org/s2n/ddt/util/threads
Usage :
//setup
PoolOptions options = new PoolOptions();
options.setCoreThreads(2);
options.setMaxThreads(33);
DdtPools.initPool("poolA", options);
Do1 p = null;
// Offer a job:
job = new YourJob();
DdtPools.offer("poolA", job);
Also do not use a cached pool as it can grow as needed, not a good idea with TCP which can block indefinately. You want to use a controlled pool. The above library can be reinitialized if needed (increase number of threads while allowing current jobs to process before the old pool is discarded to GC).
Can make a utility jsp/ servlet for those ops like https://github.com/tgkprog/ddt/blob/master/Core/src/main/web/common/poolEnd.jsp and https://github.com/tgkprog/ddt/blob/master/Core/src/main/web/common/threads.jsp
回答3:
If you have only ExecutorServivce for your application, you can proceed with static global.
newCachedThreadPool()
and newFixedThreadPool()
both does not provide control on queue of Callable/Runnable
tasks. They use unbounded queue, which may result into degraded performance of the system with respect to performance.
I prefer to use ThreadPoolExecutor which provides better control on various parameters like Queue Size, Rejection Handler, Thread factory etc.
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
Or
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
Refer to below post for more details:
FixedThreadPool vs CachedThreadPool: the lesser of two evils
来源:https://stackoverflow.com/questions/29737727/should-executorservice-be-static-and-global