Below code snippet combine Guava ListenableFuture and spring @Async for non-blocking way to fetch process result and chaining.
1. add ListeningThreadPoolTaskExecutor class to project classpath
packageorg.springframework.scheduling.concurrent;
importjava.util.concurrent.Callable;
importjava.util.concurrent.Future;
importjava.util.concurrent.RejectedExecutionException;
importorg.springframework.core.task.TaskRejectedException;
importcom.google.common.util.concurrent.ListeningExecutorService;
importcom.google.common.util.concurrent.MoreExecutors;
publicclassListeningThreadPoolTaskExecutorextendsThreadPoolTaskExecutor {
@OverridepublicFuture<?> submit(Runnabletask) {
ListeningExecutorServiceexecutor = MoreExecutors.listeningDecorator(getThreadPoolExecutor());
try {
returnexecutor.submit(task);
} catch (RejectedExecutionExceptionex) {
thrownewTaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
@Overridepublic <T> Future<T> submit(Callable<T> task) {
ListeningExecutorServiceexecutor = MoreExecutors.listeningDecorator(getThreadPoolExecutor());
try {
returnexecutor.submit(task);
} catch (RejectedExecutionExceptionex) {
thrownewTaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
}2. add taskExecutor bean defintion to xml configuration
<beanid="taskExecutor"
class="org.springframework.scheduling.concurrent.ListeningThreadPoolTaskExecutor">
<propertyname="corePoolSize"value="5" />
<propertyname="maxPoolSize"value="10" />
<propertyname="queueCapacity"value="25" />
</bean>
<task:annotation-drivenexecutor="taskExecutor" />@ServicepublicclassSearchService {
@AsyncpublicFuture<SearchResult> search(Stringkeyword) {
SearchResultresult = ... //do some blocking or heavy operation herereturnnewAsyncResult<SearchResult>(result);
}
}
@ServicepublicclassSearchApplication {
publicvoidrunWithFutureCallback() { ListenableFuture<SearchResult> future1 = (ListenableFuture<SearchResult>) searchService.search("Joshua Bloch");
Futures.addCallback(future1, newFutureCallback<SearchResult>() {
publicvoidonSuccess(SearchResultresult) {
logger.debug("search keyword:{} found:{} totalTime:{}ms", newObject[] { result.getKeyword(), result.getRecords(), result.getTotalTime() });
}
publicvoidonFailure(Throwablethrown) {
logger.warn(thrown.getMessage());
}
});
}
}For full example, please look in the src/main/java/me/brandon/application directory.
the console output from full example
2012-11-29 14:26:01,045 [main] INFO me.brandon.application.Main - starting application
2012-11-29 14:26:01,869 [taskExecutor-1] DEBUG me.brandon.application.SearchService - search keyword:Joshua Bloch
2012-11-29 14:26:01,869 [taskExecutor-3] DEBUG me.brandon.application.SearchService - search keyword:Joshua Bloch
2012-11-29 14:26:01,869 [taskExecutor-4] DEBUG me.brandon.application.SearchService - search keyword:Martin Odersky
2012-11-29 14:26:01,869 [taskExecutor-5] DEBUG me.brandon.application.SearchService - search keyword:Brian Goetz
2012-11-29 14:26:01,869 [taskExecutor-2] DEBUG me.brandon.application.SearchService - search keyword:Martin Fowler
2012-11-29 14:26:02,874 [taskExecutor-3] DEBUG me.brandon.application.SearchService - search keyword:Bruce Eckel
2012-11-29 14:26:03,871 [taskExecutor-5] DEBUG me.brandon.application.SearchService - search keyword:Martin Fowler
2012-11-29 14:26:03,871 [taskExecutor-1] DEBUG me.brandon.application.SearchApplication - search keyword:Joshua Bloch found:[Effective Java, Java Concurrency in Practice, JavaTM Puzzlers, Java Concurrency in Practice] totalTime:2002ms
2012-11-29 14:26:09,875 [taskExecutor-5] DEBUG me.brandon.application.SearchApplication - search keyword:Joshua BlochMartin OderskyBrian GoetzBruce Eckel found:[Thinking in C++, JavaTM Puzzlers, Thinking in Java, Programming in Scala, Effective Java, Java Concurrency in Practice] totalTime:7001ms
2012-11-29 14:26:10,870 [taskExecutor-2] WARN me.brandon.application.SearchApplication - the keyword 'Martin Fowler'did not match any records
2012-11-29 14:26:10,871 [main] INFO me.brandon.application.Main - leaving application