use*_*444 9 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 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);
}
}
Run Code Online (Sandbox Code Playgroud)
这由文档解决:
当在method中提交新任务
execute(java.lang.Runnable)并且corePoolSize运行的线程少于线程数量时,即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求。如果正在运行的线程多于corePoolSize但少于maximumPoolSize线程,则仅当队列已满时才创建新线程。
因此,要实现所需的行为,请增加corePoolSize或为执行程序服务提供不可增长的队列,如下所示:
ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 20,
100000, TimeUnit.MILLISECONDS,
new SynchronousQueue<Runnable>());
Run Code Online (Sandbox Code Playgroud)
此行为是由于 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);
}
Run Code Online (Sandbox Code Playgroud)