当ThreadPoolExecutor的所有任务完成执行作业时插入数据库

时间:2012-08-20 01:55:22

标签: java multithreading executorservice threadpoolexecutor

问题定义: -

一旦insert some values into Database的所有任务完成了那些工作,我就需要ExecutorService。换句话说,我只能在所有任务完成执行作业时insert into database,因为我需要插入到db中的事情,取决于完成任务的所有线程..

所以我如何检查ExecutorService的所有任务是否已经完成执行,然后开始插入数据库。

以下是我使用ThreadPoolExecutor创建任务的代码。

executorService = new ThreadPoolExecutor(
    noOfThreads, 
    noOfThreads, 
    500L, 
    TimeUnit.MILLISECONDS,
    new ArrayBlockingQueue<Runnable>(noOfThreads), 
    new ThreadPoolExecutor.CallerRunsPolicy()
);


// Running for particular duration of time
while(System.currentTimeMillis() <= endTime) {
    Command newCommand = getNextCommand();
    Task nextRunnable = new Task(newCommand, existId, newId);
    executorService.submit(nextRunnable); // Submit it for execution
}

/* 
    Previously I was inserting into database here, but it was wrong as it might be 
    possible that some threads are still in progress. And If I am inserting right here 
    into database, then some information I will be loosing for sure. So how can I check 
    whether all the tasks have finished executing and then I can insert into database.
*/      
executorService.shutdown();
if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)) {
    executorService.shutdownNow();
}

我将用于插入的代码位于 -

之下
// Inserting into Database when all the task have finished executing, currently I
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : GUID_ID_MAPPING.entrySet()) {
    pstatement = db_connection.prepareStatement(LnPConstants.UPSERT_SQL);
    pstatement.setInt(1, entry.getKey());
    pstatement.setString(2, entry.getValue().get(LnPConstants.CGUID_ID));
    pstatement.setString(3, entry.getValue().get(LnPConstants.PGUID_ID));
    pstatement.executeUpdate();
}

所以我需要在所有任务完成执行后将其置于某个地方。

更新: -

所以这样的东西 -

executorService.shutdown();
if (!executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)) {
    executorService.shutdownNow();
}

// Now Insert into Database when all the task have finished executing
for (Entry<Integer, LinkedHashMap<Integer, String>> entry : GUID_ID_MAPPING.entrySet()) {
    pstatement = db_connection.prepareStatement(PDSLnPConstants.UPSERT_SQL);
    pstatement.setInt(1, entry.getKey());
    pstatement.setString(2, entry.getValue().get(PDSLnPConstants.CGUID_ID));
    pstatement.setString(3, entry.getValue().get(PDSLnPConstants.PGUID_ID));
    pstatement.executeUpdate();
}

2 个答案:

答案 0 :(得分:3)

你基本上已经有了答案。等待executorService.awaitTermination返回,执行者将完成所有任务。

这会忽略由于错误而可能失败的任务。另一种方法是执行此操作并检查错误,例如,

 List<Future> futures = ...
 for(...) {
      futures.add(executor.submit(...));
 }

 for(Future f : futures) {
       //this will throw an exception if an exception
       //occurred executing the task, insert error handling as 
       //appropriate, perhaps calling cancel on tasks that
       //have not yet completed
       f.get();
 }
 //at this point all tasks have completed

另一个要关注的课程是ExecutorCompletionService。 ExecutorCompletionService允许您按照实际完成的顺序获取任务。

答案 1 :(得分:2)

似乎是使用ExecutorCompletionService的好用例,你想过吗? Check JavaDoc for ExecutorCompletionService 你可以做这样的事情

//wrap your threadpoolexecutor ECS
ExecutorCompletionService<Boolean> ecs=new ExecutorCompletionService<Boolean>(executorService)
// submit task to ECS
ecs.submit(nextRunnable);
int noOfTasks=0;
// Running for particular duration of time
while(System.currentTimeMillis() <= endTime) {
    Command newCommand = getNextCommand();
    Task nextRunnable = new Task(newCommand, existId, newId);
    ecs.submit(nextRunnable, Boolean.TRUE); // Submit it for execution
    noOfTasks++;
    }
//Now we can use ECS to tell us what tasks are finished
for (int i=0;i<noOfTasks;i++){
 try {    
 //This is blocking call it would block until anyone of the task submitted is completed.
   Boolean result=ecs.take.get();
 // do something if you would like to handle result, you can also design to pass some unique id       instead of Boolean so that you can keep track of what tasks are completed
     }catch(ExecutionException e){//do error handling for task failure here}
     }
  //once you are here you are sure that all tasks are completed, call your database code here, you can wrap whole segment into try catch finally and close ExecutorCompletionservie