ThreadPoolExecutor运行应用程序

时间:2013-02-27 16:10:34

标签: java multithreading threadpool

结算类具有与国家明智结算相关的所有逻辑。它从数据库中获取结果,然后向用户收费。计费类实现了Runnable。我想根据国家参数并行执行Billing,这样就可以非常快速地收取大量用户(500万+)。现在需要花费数小时才能完成。

我正在尝试实现ThreadPoolExecutor来执行Billing类但我很困惑怎么办?以下有什么区别或我做错了什么?请建议!!共有20个国家,但我只在这里粘贴了5.

 //for 20 countries  ThreadPoolExecutor (20,20,20.......)????

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS, 
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());

executor.execute(new Billing("UK")); 
executor.execute(new Billing("USA")); 
executor.execute(new Billing("Germany")); 
executor.execute(new Billing("Spain")); 
executor.execute(new Billing("Italy")); 

OR

ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS, 
new ArrayBlockingQueue<Runnable>(10), new ThreadPoolExecutor.CallerRunsPolicy());
for(int i=0;i<5;i++) // for 20 countries   i<20??
{    

   executor.execute(new Billing("UK")); 
   executor.execute(new Billing("USA")); 
   executor.execute(new Billing("Germany")); 
   executor.execute(new Billing("Spain")); 
   executor.execute(new Billing("Italy")); 
}

while (! executor.isTerminated()) {
   try{
      executor.awaitTermination(100, TimeUnit.SECONDS);
   }catch(InterruptedException iE)
   {
      iE.printStackTrace();
      System.out.println("Executor Exception: "+ iE);
   }

提前致谢!!

6 个答案:

答案 0 :(得分:1)

循环解决方案似乎不对。无需多次执行相同的Runnable

您将ThreadPoolExecutorcorePoolSize都设置为maximumPoolSize来实例化5,这意味着执行程序会将池中的线程数保持为{{1}即使他们闲着也是如此。它还说池中只有5个线程。

有了这个,你可以期望大多数5线程并行执行任务(5对象)。

当您继续使用Billing方法向Billing提交executor个对象时,它们会被添加到您提供的execute中。此队列的大小为ArrayBlockingQueue。在某些情况下,队列可能已处于其最大容量且无法执行更多任务,在这种情况下,任务将被拒绝并提供给10构造函数中提供的RejectedExecutionHandler。它的工作是使用实现的方法ThreadPoolExecutor来处理被拒绝的任务。

如果您想查找是否有任何被拒绝的任务,您必须提供自己的rejectedExecution,而不是使用默认的RejectedExecutionHandler。你可以这样做:

ThreadPoolExecutor.CallerRunsPolicy

答案 1 :(得分:1)

首先:忘记循环

for(int i=0;i<5;i++) // for 20 countries   i<20??
{    

   executor.execute(new Billing("UK")); 
   executor.execute(new Billing("USA")); 
   executor.execute(new Billing("Germany")); 
   executor.execute(new Billing("Spain")); 
   executor.execute(new Billing("Italy")); 
}

这会多次循环所有账单。

正确的做法是在第一个片段中:

executor.execute(new Billing("UK")); 
executor.execute(new Billing("USA")); 
executor.execute(new Billing("Germany")); 
executor.execute(new Billing("Spain")); 
executor.execute(new Billing("Italy")); 

另一个错误在于终止检查:

while (! executor.isTerminated()) {
   try{
      executor.awaitTermination(100, TimeUnit.SECONDS);
   }catch(InterruptedException iE)
   {
      iE.printStackTrace();
      System.out.println("Executor Exception: "+ iE);
   }
}

Executor.awaitTermination的javadoc说:

  

阻止所有任务在关闭请求后完成执行,

但您永远不会发出关机请求。

在您的情况下,您可以使用ExecutorCompletionService,如下所示:

CompletionService<String> ecs = new ExecutorCompletionService<String>(executor);
List<String> countries= Arrays.asList("UK","USA","Germany","Spain","Italy");   
for(String country : countries) {
    ecs.submit(new Billing(country),country);
}
// wait for completion
for(int i=0;i<countries.size();i++){
      ecs.take(); // wait for next country completion
}
// all work completed, shutdown
executor.shutdownNow();

答案 2 :(得分:0)

我不确定你是否了解循环是如何工作的。不同之处在于,第二个代码块将在每个列出的国家/地区运行5次计费。

答案 3 :(得分:0)

假设您正在讨论代码的for循环部分,那么它的工作原理并不明显。

理想情况下,循环看起来像这样:

for(String country : countryCollection) {
    executor.execute(new Billing(country));
}

答案 4 :(得分:0)

您是否考虑过使用enum

static class Billing implements Runnable {

  enum Country {
    UK,
    USA,
    Germany,
    Spain,
    Italy;
  }

  public Billing(Country country) {
  }

  @Override
  public void run() {
  }
}
public void test() {
  ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 5, 5, TimeUnit.SECONDS,
       new ArrayBlockingQueue<Runnable>(10), 
          new ThreadPoolExecutor.CallerRunsPolicy());
  for ( Billing.Country country : Billing.Country.values() ) {
    executor.execute(new Billing(country));
  }
}

答案 5 :(得分:0)

考虑实施此问题的另一种方法是查看The Fork/Join Framework。这似乎真的可以从钢铁工作中受益。例如,你可以看起来相当干净地打破它。这基本上允许您分解用户或用户子集的计费任务,而不是让一个看似代表一个国家的线程通过其所有计费工作。

您可以找到图书馆的链接:here if you are using a version of Java < 7