2013-07-27 34 views
7

如果我运行持久性任务如果第一个任务尚未完成,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); 
    } 
} 

回答

3

此行为是由于到新的线程将添加,如果有一个未能提供到队列中的任务的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); 
     } 
3

ExecutorService.execute()的Javadoc说:

在未来某个时间执行给定的命令。该命令可以在执行程序执行的判断下在新线程,池线程或调用线程中执行。

任务可以在一个新的线程或在现有的线程中执行:

这是通过Javadoc文档ThreadPoolExecutor.execute(),它说加强。

原因在源解释评论ThreadPoolExecutor.execute()它说:

如果一个任务可以成功排队,然后我们做了

和bit later

如果我们不能排队的任务,那么我们尝试添加一个新的线程

由于您的队列是无界的,其他任务可以排队,因此也不会创建新的线程执行以下任务。

只有当任务不能排队时,才会创建更多线程。

+0

你应该已经看过了'ThreadPoolExecutor'类的Javadoc :) –

+0

@MarkoTopolnik javadoc没有答案!查看我的编辑 – Bohemian

+0

你怎么看?你有看到我的报价吗?它预测到底会发生什么,以及要修改的内容。 –

4

这是由文档解决:

当一个新的任务在方法execute(java.lang.Runnable)提交,少于corePoolSize线程在运行,创建一个新的线程来处理请求,即使其他辅助线程闲置。如果有多于corePoolSize但小于maximumPoolSize的线程正在运行,则仅当队列已满时,才会创建一个新线程

那么,要实现你想要的行为,无论是增加corePoolSize或给执行业务的非可扩展的队列,像这样:

ExecutorService checkTasksExecutorService = new ThreadPoolExecutor(1, 20, 
    100000, TimeUnit.MILLISECONDS, 
    new SynchronousQueue<Runnable>());