Kan*_*mar 19 java multithreading
我尝试过创建和执行ThreadPoolExecutor
int poolSize = 2;
int maxPoolSize = 3;
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(2);
Run Code Online (Sandbox Code Playgroud)
如果我连续尝试7日,8日......任务
threadPool.execute(task);
Run Code Online (Sandbox Code Playgroud)
在队列达到最大大小后,
它开始抛出"RejectedExecutionException".意味着我失去了添加这些任务.
在这里,如果BlockingQueue缺少任务,那么它的作用是什么?意味着它为什么不等待?
从BlockingQueue的定义
一个队列,它还支持在检索元素时等待队列变为非空的操作,并在存储元素时等待队列中的空间可用.
为什么我们不能使用linkedlist(正常队列实现而不是阻塞队列)?
Kir*_*ril 16
出现此问题的原因是您的任务队列太小,这由execute方法的文档指示:
将来某个时候执行给定的任务.任务可以在新线程或现有池化线程中执行.如果无法提交执行任务,或者因为此执行程序已关闭或已达到其容量,则该任务由当前的RejectedExecutionHandler处理.
所以第一个问题是你将队列大小设置为一个非常小的数字:
int poolSize = 2;
int maxPoolSize = 3;
ArrayBlockingQueue<Runnable> queue = new ArrayBlockingQueue<Runnable>(2);
Run Code Online (Sandbox Code Playgroud)
然后你说"如果[我]尝试第7,第8 ......任务"那么你会得到一个,RejectedExecutionException因为你超过了队列的容量.有两种方法可以解决您的问题(我建议两者兼顾):
你应该有类似的东西:
public void ExecuteTask(MyRunnableTask task) {
bool taskAdded = false;
while(!taskAdded) {
try {
executor.execute(task);
taskAdded = true;
} catch (RejectedExecutionException ex) {
taskAdded = false;
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,解决你的其他问题......
在这里,如果BlockingQueue缺少任务,那么它的作用是什么?
它的作用BlockingQueue是完成生产者/消费者模式,如果它足够大,那么你不应该看到你遇到的问题.如上所述,您需要增加队列大小并捕获异常,然后重试执行任务.
为什么我们不能使用链表?
链表既不是线程安全的,也不是阻塞的.生产者/消费者模式倾向于使用阻塞队列最佳.
请不要被以下陈述所冒犯,我故意使用更严格的语言,以便强调你的第一个假设永远不应该是你正在使用的库有什么问题(除非你写的图书馆自己,你知道它有一个特定的问题)!
所以我们现在就把这个问题放在一边:既不ThreadPoolExecutor是Java库也不是Java库.这完全是你(错误)使用库造成了问题.Javmex有一个很好的教程,解释你所看到的确切情况.
可能有几个原因导致您填充队列的速度比清空队列要快:
还有很多其他原因,但我认为以上是最常见的.
我会给你一个带有无界队列的简单解决方案,但它不能解决你对这个库的错误使用问题.因此,在我们指责Java库之前,让我们看一个简洁的示例来演示您遇到的确切问题.
以下是解决具体问题的其他几个问题:
gka*_*mal 12
阻塞队列主要用于使用者(池中的线程).线程可以等待队列中的新任务可用,它们将自动被唤醒.简单的链表不会用于此目的.
在生产者端,默认行为是在队列已满时抛出异常.这可以通过实现自己的RejectedExceptionHandler轻松定制.在您的处理程序中,您可以获取队列并调用将阻塞的put方法,直到有更多空间可用.
但这不是一件好事 - 原因是如果这个执行器出现问题(死锁,处理速度慢),它会对系统的其余部分产生连锁反应.例如,如果从servlet调用execute方法 - 如果execute方法阻塞,那么所有容器线程都会被挂起,你的应用程序将停止运行.这可能是默认行为是抛出异常而不是等待的原因.此外,没有实现RejectedExceptionHandler来执行此操作 - 阻止人们使用它.
在调用线程中有一个选项(CallersRunPolicy),如果你想要进行处理,它可以是另一个选项.
一般规则是 - 最好不要处理一个请求,而不是整个系统崩溃.您可能想了解断路器模式.
| 归档时间: |
|
| 查看次数: |
23915 次 |
| 最近记录: |