Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用Executors服务在Java中创建固定大小线程池的最佳方法_Java_Multithreading_Threadpool_Executorservice - Fatal编程技术网

使用Executors服务在Java中创建固定大小线程池的最佳方法

使用Executors服务在Java中创建固定大小线程池的最佳方法,java,multithreading,threadpool,executorservice,Java,Multithreading,Threadpool,Executorservice,我正在使用Java中的Executors框架为多线程应用程序创建线程池,我有一个与性能相关的问题 我有一个应用程序,可以在实时或非实时模式下工作。如果是实时的,我只是使用以下方法: THREAD_POOL = Executors.newCachedThreadPool(); 但如果不是实时的,我希望能够控制线程池的大小。 要做到这一点,我考虑了两种选择,但我并不真正理解其中的区别,以及哪一种表现更好 选项1使用简单的方法: THREAD_POOL = Executors.newFixedThr

我正在使用Java中的
Executors
框架为多线程应用程序创建线程池,我有一个与性能相关的问题

我有一个应用程序,可以在实时或非实时模式下工作。如果是实时的,我只是使用以下方法:

THREAD_POOL = Executors.newCachedThreadPool();
但如果不是实时的,我希望能够控制线程池的大小。 要做到这一点,我考虑了两种选择,但我并不真正理解其中的区别,以及哪一种表现更好

选项1使用简单的方法:

THREAD_POOL = Executors.newFixedThreadPool(threadPoolSize);
选项2是创建我自己的
ThreadPoolExecutor
,如下所示:

RejectedExecutionHandler rejectHandler = new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
    try {
        executor.getQueue().put(r);
    } catch (Exception e) {}
}
};          
THREAD_POOL = new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(10000), rejectHandler);
RejectedExecutionHandler rejectHandler=新的RejectedExecutionHandler(){
@凌驾
public void rejectedExecution(可运行的r、线程池执行器执行器){
试一试{
executor.getQueue().put(r);
}捕获(例外e){}
}
};          
THREAD_POOL=new ThreadPoolExecutor(threadPoolSize,threadPoolSize,0,TimeUnit.SECONDS,new LinkedBlockingQueue(10000),rejectHandler);

我想了解使用更复杂的选项2的优势是什么,以及我是否应该使用比
LinkedBlockingQueue
更复杂的数据结构?任何帮助都将不胜感激。

查看源代码,您将意识到:

Executors.newFixedThreadPool(threadPoolSize);
相当于

return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, 0L, MILLISECONDS,
                              new LinkedBlockingQueue<Runnable>());
返回新的ThreadPoolExecutor(threadPoolSize,threadPoolSize,0L,毫秒,
新建LinkedBlockingQueue());
由于它不提供显式的
RejectedExecutionHandler
,因此使用默认的
AbortPolicy
。一旦队列已满,它基本上会抛出
RejectedExecutionException
。但是队列是无限的,所以它永远不会满。因此,该执行器接受inifnite1数量的任务

您的声明要复杂得多,而且完全不同:

  • newlinkedblockingqueue(10000)
    如果等待的任务超过10000个,则会导致线程池放弃任务

  • 我不明白你的
    RejectedExecutionHandler
    在做什么。如果池发现它不能将更多的可运行程序放入队列,它将调用您的处理程序。在这个处理器中,您。。。尝试再次将
    Runnable
    放入队列(在99%的案例块中会失败)。最后你接受了这个例外。看起来像是
    ThreadPoolExecutor。丢弃策略是您所追求的

    若任务队列太大,查看下面的评论似乎是在试图阻止或以某种方式限制客户端。我不认为在
    RejectedExecutionHandler
    内部阻塞是个好主意。取而代之的是考虑<代码> CallerRunsPolicy <代码>拒绝策略。不完全一样,但足够近

总而言之:如果您想限制挂起任务的数量,您的方法几乎是好的。如果您想限制并发线程的数量,第一行就足够了


1-假设2^31为无穷大

RejectedExecutionHandler
实际上正在阻塞,调用
executor.getQueue().put(r)
将一直阻塞,直到队列释放,因此最终我的处理程序允许保留一个有界队列而不中止任何任务。除非我弄错了+1了解其他细节。@charlesmengy:谢谢你的澄清,我的错,我会更新我的问题。但是,通过在
RejectedExecutionHandler
内部阻塞,您希望实现什么呢?我相信它可能会有一些意想不到的副作用,比如阻塞调用线程。也许你需要
callerunpolicy
?实际上看了之后,
callerunpolicy
听起来对我想做的事情很有希望,我会试试的谢谢!也许你可以在答案中加上这个,我会接受你的答案。