
com.liveramp.java_support.concurrent.ParallelUtil Maven / Gradle / Ivy
The newest version!
package com.liveramp.java_support.concurrent;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ParallelUtil {
public static Future call(Callable callable) {
ExecutorService executorService = Executors.newSingleThreadExecutor(new DaemonThreadFactory());
Future submit = executorService.submit(callable);
return new CloseExecutorFuture(submit, executorService);
}
public static List> call(List extends Callable> callable) {
ExecutorService executorService = Executors.newSingleThreadExecutor(new DaemonThreadFactory());
List> result = new ArrayList<>();
for (Callable tCallable : callable) {
Future submit = executorService.submit(tCallable);
result.add(new CloseExecutorFuture(submit, executorService));
}
for (CloseExecutorFuture tCloseExecutorFuture : result) {
tCloseExecutorFuture.setOthers(result);
}
return (List>)(List)result; //java is so incredibly stupid
}
public static List> call(Callable callable, Callable... callables) {
ArrayList> callable1 = new ArrayList<>();
callable1.add(callable);
callable1.addAll(Arrays.asList(callables));
return call(callable1);
}
public static List> time(Runnable runnable, Runnable... runnables) {
ArrayList runnables1 = new ArrayList<>();
runnables1.add(runnable);
runnables1.addAll(Arrays.asList(runnables));
return time(runnables1);
}
public static Future time(Runnable runnable) {
return time(Collections.singletonList(runnable)).get(0);
}
public static List> time(List runnables) {
List collect = runnables.stream().map(TimedRunnable::new).collect(Collectors.toList());
return call(collect);
}
@Deprecated
public static List await(List> futures) {
return awaitIgnoringPotentialErrors(futures);
}
static List awaitIgnoringPotentialErrors(Collection> futures) {
return futures.stream().map(f -> {
try {
return f.get();
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}).collect(Collectors.toList());
}
//Wait on a series of future to complete, but check each future with a timeout in a loop to ensure that any
//errors in the futures are thrown immediately.
public static void awaitErrorSafe(Collection> futures, long waitBetweenLoops, TimeUnit amount) {
boolean allComplete = false;
while (!allComplete) {
try {
amount.sleep(waitBetweenLoops);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
allComplete = true;
for (Future> future : futures) {
try {
future.get(1, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
allComplete = false;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
public static void awaitErrorSafe(Collection> futures) {
awaitErrorSafe(futures, 1, TimeUnit.SECONDS);
}
private static class TimedRunnable implements Callable {
Runnable r;
public TimedRunnable(Runnable r) {
this.r = r;
}
@Override
public Long call() throws Exception {
long start = System.currentTimeMillis();
r.run();
return System.currentTimeMillis() - start;
}
}
private static class CloseExecutorFuture implements Future {
Future internal;
ExecutorService service;
boolean done;
List> others = new ArrayList<>();
public CloseExecutorFuture(Future internal, ExecutorService service) {
this.internal = internal;
this.service = service;
}
public void setOthers(List> others) {
this.others = others;
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
boolean cancel = internal.cancel(mayInterruptIfRunning);
tryShutdown();
return cancel;
}
private void tryShutdown() {
this.done = true;
if (othersDone()) {
service.shutdown();
}
}
private boolean othersDone() {
for (CloseExecutorFuture other : others) {
if (!other.done) {
return false;
}
}
return true;
}
@Override
public boolean isCancelled() {
return internal.isCancelled();
}
@Override
public boolean isDone() {
return internal.isDone();
}
@Override
public T get() throws InterruptedException, ExecutionException {
T t = internal.get();
tryShutdown();
return t;
}
@Override
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
T t = internal.get(timeout, unit);
tryShutdown();
return t;
}
}
private static Logger LOG = LoggerFactory.getLogger(ParallelUtil.class);
public static boolean runWithTimeout(Runnable r, long timeout, TimeUnit unit) {
Optional
© 2015 - 2025 Weber Informatics LLC | Privacy Policy