packagecom.hao.service;importjava.util.ArrayList;importjava.util.Arrays;importjava.util.LinkedList;importjava.util.List;importjava.util.concurrent.Callable;importjava.util.concurrent.CountDownLatch;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Future;importjava.util.concurrent.TimeUnit;importjavax.annotation.PostConstruct;importorg.springframework.stereotype.Service;importcom.google.common.base.Preconditions;
@Servicepublic classExecutorContext {publicExecutorService executorService;private int DEFAULT_WAIT_SECONDS = 2;
@PostConstructpublic voidinit() {
executorService=ExecutorManager.threadPoolExecutor;
}public List waitAllFutures(List> calls, int milliseconds) throwsException {
Preconditions.checkArgument(null != calls && !calls.isEmpty(), "callable empty.");
LatchedCallables latchAndCallables =wrapCallables(calls);
List> futurres = new LinkedList<>();for (CountdownedCallablecallable : latchAndCallables.wrappedCallables) {if (null !=callable) {
futurres.add(executorService.submit(callable));
}
}
List rets = new ArrayList<>();if(latchAndCallables.latch.await(milliseconds, TimeUnit.MILLISECONDS)) {for (CountdownedCallablecall : latchAndCallables.wrappedCallables) {
rets.add(call.getResult());
}
}else{for (Futurefuture : futurres) {if (!future.isDone()) {
future.cancel(true);
}
}
}returnrets;
}public List waitAllCallables(List> calls, int seconds) throwsException {
Preconditions.checkArgument(null != calls && !calls.isEmpty(), "callable empty.");
LatchedCallables latchAndCallables =wrapCallables(calls);for (CountdownedCallablecallable : latchAndCallables.wrappedCallables) {
executorService.submit(callable);
}
List rets = new ArrayList<>();if(latchAndCallables.latch.await(seconds, TimeUnit.SECONDS)) {for (CountdownedCallablecall : latchAndCallables.wrappedCallables) {
rets.add(call.getResult());
}
}returnrets;
}public List waitAllCallables(@SuppressWarnings("unchecked") Callable... calls) throwsException {
Preconditions.checkNotNull(calls,"callable empty.");returnwaitAllCallables(Arrays.asList(calls), DEFAULT_WAIT_SECONDS);
}private static LatchedCallables wrapCallables(List>callables) {
CountDownLatch latch= newCountDownLatch(callables.size());
List> wrapped = new ArrayList<>(callables.size());for (Callablecallable : callables) {
wrapped.add(new CountdownedCallable<>(callable, latch));
}
LatchedCallables returnVal = new LatchedCallables<>();
returnVal.latch=latch;
returnVal.wrappedCallables=wrapped;returnreturnVal;
}public static class LatchedCallables{publicCountDownLatch latch;public List>wrappedCallables;
}public static class CountdownedCallable implements Callable{private final Callablewrapped;private finalCountDownLatch latch;privateT result;public CountdownedCallable(Callablewrapped, CountDownLatch latch) {this.wrapped =wrapped;this.latch =latch;
}
@Overridepublic T call() throwsException {try{
result=wrapped.call();returnresult;
}finally{
latch.countDown();
}
}publicT getResult() {returnresult;
}
}
}