public abstract class ConcurrentExecuteService<T> {
private int timeout = 5;
private TimeUnit timeUnit = TimeUnit.SECONDS;
private ScheduledExecutorService delayer;
private ExecutorService executorService;
public ConcurrentExecuteService(ExecutorService executorService, int delayerSize) {
this.executorService = executorService;
delayer = Executors.newScheduledThreadPool(delayerSize);
}
public ConcurrentExecuteService(ExecutorService executorService, int delayerSize, ThreadFactory threadFactory) {
this.executorService = executorService;
delayer = Executors.newScheduledThreadPool(delayerSize, threadFactory);
}
protected abstract T defaultValue();
public List<T> execute(List<Callable<T>> tasks) {
return executeSuppliers(tasks.stream().map(mapToSupplier()).collect(Collectors.toList()));
}
private Function<Callable<T>, Supplier<T>> mapToSupplier() {
return callable -> (Supplier<T>) () -> {
try {
return callable.call();
} catch (Exception e) {
return defaultValue();
}
};
}
private List<T> executeSuppliers(List<Supplier<T>> suppliers) {
List<CompletableFuture<T>> supplierFutures = suppliers.stream().map(supplier -> mapToCompletableFuture(supplier)).collect(Collectors.toList());
CompletableFuture<Void> completableFuture = CompletableFuture.allOf(supplierFutures.toArray(new CompletableFuture[supplierFutures.size()]));
try {
return completableFuture.thenApply(future -> supplierFutures.stream().map(supplierFuture -> supplierFuture.join()).collect(Collectors.toList())).get();
} catch (Exception e) {
return Lists.newArrayList();
}
}
private CompletableFuture<T> mapToCompletableFuture(Supplier<T> supplier) {
return CompletableFuture.supplyAsync(supplier, executorService).applyToEither(timeoutAfter(), Function.identity());
}
public CompletableFuture<T> timeoutAfter() {
CompletableFuture<T> result = new CompletableFuture<>();
delayer.schedule(() -> result.complete(defaultValue()), timeout, timeUnit);
return result;
}
public int getTimeout() {
return timeout;
}
public void setTimeout(int timeout) {
this.timeout = timeout;
}
public TimeUnit getTimeUnit() {
return timeUnit;
}
public void setTimeUnit(TimeUnit timeUnit) {
this.timeUnit = timeUnit;
}
}