Muddassir Rahman
Muddassir Rahman

Reputation: 956

how to make main thread wait for executor service threads to complete

Here is my main thread , inside each process i am calling executor service threads. At line 4 , before updating the status , i want to wait for my all threads to complete

 line 1- missingStrategyContext.process(FileType.CARD, programId, fromDate, toDate, channel);
 line 2- missingStrategyContext.process(FileType.TRANSACTION, programId, fromDate, toDate, channel);
 line 3- missingStrategyContext.process(FileType.REFUND, programId, fromDate, toDate, channel);

 line 4- processingLog.setProcessingStatus(TransactionState.SUCCESS.name());

Inside each process i am deciding on file type value which strategy i have to call

public void process(FileType fileType, String programId, Long fromDate, Long toDate, String channel){
    map.get(fileType).process(programId, fromDate, toDate, channel, fileType);
}

and then depending on file type i have implemented my process method and called executor service in each file type implementation

@Override
public void process(String programId, Long fromDate, Long toDate, String channel, FileType fileType) {

    MultiTenantTxMgmt multiTenantTxMgmt = MultiTenantTxMgmtUtil.get(programId);
    EntityManager entityManager = null;

    List<MissingReason> reasonList = new ArrayList<>();
    try {
        entityManager = multiTenantTxMgmt.getEntityManager();
        reasonList = missingDataRepository.getDistinctMissingReasonForFileType(entityManager, fileType, TransactionState.READYTOATTEMPT);
    }catch (Exception exception) {
        logger.error(exception.getMessage(), exception);
        throw new UnkownBatchSaveException();
    } finally {
        entityManager.close();
    }

    reasonList.forEach(
            missingReason -> deExecutorService.dotask(() ->
                    missingTransactionStrategyContext.processMissingV3(missingReason, programId, fromDate, toDate, channel, fileType)
            )
    );

}

Upvotes: 1

Views: 421

Answers (2)

Michael Kreutz
Michael Kreutz

Reputation: 1256

You could make doTask method let return a (completable) future (if it does not already) and return a list of futures in method process, e.g. replace

reasonList.forEach(
            missingReason -> deExecutorService.dotask(() ->
                    missingTransactionStrategyContext.processMissingV3(missingReason, programId, fromDate, toDate, channel, fileType)
            )
    );

with

    final List<Future> futures = reasonList.stream()
        .map(missingReason -> deExecutorService.dotask(() ->
            missingTransactionStrategyContext
                .processMissingV3(missingReason, programId, fromDate, toDate, channel, fileType)))
        .collect(Collectors.toList());

  }
return futures;

Then in your calling part you can wait on all these futures to terminate before continuing.

Upvotes: 0

Aniket Sahrawat
Aniket Sahrawat

Reputation: 12937

You can use CountDownLatch#await. Eg copied from docs:

CountDownLatch startSignal = new CountDownLatch(1);
CountDownLatch doneSignal = new CountDownLatch(N);

for (int i = 0; i < N; ++i) // create and start threads
    new Thread(new Worker(startSignal, doneSignal)).start();

doSomethingElse();            // don't let run yet
startSignal.countDown();      // let all threads proceed
doSomethingElse();
doneSignal.await();           // wait for all to finish

Upvotes: 2

Related Questions