Java 执行器未按预期处理任务
若我运行持久任务,若第一个任务并没有完成,Executor就不会启动新线程。有人能帮我理解为什么以及如何解决这个问题吗Java 执行器未按预期处理任务,java,concurrency,executor,Java,Concurrency,Executor,若我运行持久任务,若第一个任务并没有完成,Executor就不会启动新线程。有人能帮我理解为什么以及如何解决这个问题吗 import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import or
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import org.junit.Test;
public class TestExecutor {
@Test
public void test() throws InterruptedException {
ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 10,
100000, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
for (int i = 0; i < 20; i++) {
checkTasksExecutorService.execute(new Runnable() {
public void run(){
try {
System.out.println(Thread.currentThread().getName() + " running!");
Thread.sleep(10000);
} catch (Exception e) {
}
}
});
}
Thread.sleep(1000000);
}
}
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.LinkedBlockingQueue;
导入java.util.concurrent.ThreadPoolExecutor;
导入java.util.concurrent.TimeUnit;
导入org.junit.Test;
公共类测试器{
@试验
public void test()引发InterruptedException{
ExecutorService checkTasksExecutorService=新的线程池执行器(1,10,
100000,时间单位为毫秒,
新建LinkedBlockingQueue());
对于(int i=0;i<20;i++){
checkTasksExecutorService.execute(新的可运行(){
公开募捐{
试一试{
System.out.println(Thread.currentThread().getName()+“running!”);
睡眠(10000);
}捕获(例外e){
}
}
});
}
线程。睡眠(1000000);
}
}
此行为是由于ThreadPoolExecutor中的逻辑造成的,如果无法向队列提供任务,则会在ThreadPoolExecutor中添加新线程。您的队列是无边界的,因此这实际上意味着我们永远不会超过核心池大小并达到最大池大小
请尝试此示例以查看差异:
ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 10,
100000, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
for (int i = 0; i < 10; i++) {
checkTasksExecutorService.execute(new Runnable() {
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " running!");
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
//Thread.sleep(1000000); //instead this use following
//stop accepting new tasks
checkTasksExecutorService.shutdown();
while (!checkTasksExecutorService.isTerminated()) {
Thread.sleep(100);
}
ExecutorService checktasksecutorservice=新线程池执行器(1,10,
100000,时间单位为毫秒,
新建SynchronousQueue());
对于(int i=0;i<10;i++){
checkTasksExecutorService.execute(新的可运行(){
公开募捐{
试一试{
System.out.println(Thread.currentThread().getName()+“running!”);
睡眠(1000);
}捕获(例外e){
e、 printStackTrace();
}
}
});
}
//线程。睡眠(1000000)//取而代之的是使用以下方法
//停止接受新任务
checkTasksExecutorService.shutdown();
而(!checkTasksExecutorService.isTerminated()){
睡眠(100);
}
ExecutorService.execute()的javadoc说明:
在将来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由执行者实现决定
javadoc forThreadPoolExecutor.execute()
,进一步强化了这一点,它说:
任务可以在新线程或现有线程中执行
但是ThreadPoolExecutor.execute()
的源代码注释解释了原因,其中指出:
如果任务可以成功排队,那么我们就完成了
过一会儿
如果无法将任务排队,则尝试添加新线程
由于队列是无界的,因此可以对更多任务进行排队,因此不会创建新线程来执行以下任务
只有当任务无法排队时,才会创建更多线程。这由文档解决:
在方法execute(java.lang.Runnable)
中提交新任务时,如果运行的线程少于corePoolSize
线程,则会创建一个新线程来处理该请求,即使其他工作线程处于空闲状态。如果运行的线程数大于corePoolSize
但小于maximumPoolSize
,则仅当队列已满时才会创建新线程
因此,要实现您想要的行为,请增加corePoolSize
或为executor服务提供一个不可增长的队列,如下所示:
ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 20,
100000, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
ExecutorService checktasksecutorservice=新线程池执行器(1,20,
100000,时间单位为毫秒,
新建SynchronousQueue());
你应该看看ThreadPoolExecutor
类Javadoc:)@MarkoTopolnik Javadoc没有答案!看我的编辑秀,你觉得呢?你看到我的报价了吗?它准确地预测将会发生什么,以及要改变什么来修复它。