3

問題の定義:-

insert some values into DatabaseのすべてのタスクがExecutorServiceそこでジョブの実行を終了したらすぐに実行する必要があります。言い換えると、insert into databasedbに挿入する必要があるものは、そこでタスクを終了するすべてのスレッドに依存しているため、すべてのタスクがそこでジョブの実行を終了した場合にのみ実行できます。

では、のすべてのタスクの実行が終了したかどうかを確認し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();
}

したがって、すべてのタスクの実行が終了した後、このforループをどこかに配置する必要があります。

アップデート:-

だからこのようなもの-

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();
}
4

2 に答える 2

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

注目すべきもう1つのクラスはExecutorCompletionServiceです。ExecutorCompletionServiceを使用すると、実際に完了した順序でタスクを取得できます。

于 2012-08-20T02:24:19.247 に答える
2

ExecutorCompletionServiceを使用する良いユースケースのようですが、それについて考えたことはありますか? JavaDocで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
于 2012-08-20T03:06:58.333 に答える