cn.keayuan.util.Task Maven / Gradle / Ivy
The newest version!
package cn.keayuan.util;
import java.util.concurrent.Callable;
import java.util.concurrent.CancellationException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executor;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import cn.keayuan.util.function.BiConsumer;
import cn.keayuan.util.function.Consumer;
public final class Task extends FutureTask {
private final Pair, V>, Executor> success;
private final Pair, Throwable>, Executor> error;
private final Pair>, Executor> cancel;
private final Consumer> complete;
private final String tag;
private volatile boolean timeout;
private Task(Builder builder) {
super(builder.callable);
success = builder.success;
error = builder.error;
cancel = builder.cancel;
complete = builder.complete;
tag = builder.tag;
}
@Override
protected void done() {
if (isCancelled()) {
callback(cancel, null, null, true);
return;
}
if (timeout) {
return;
}
try {
V v = get();
callback(success, v, null, false);
} catch (ExecutionException | InterruptedException e) {
callback(error, null, e, false);
}
}
private void get(long timeout) {
try {
get(timeout, TimeUnit.MILLISECONDS);
} catch (CancellationException ignore) {
} catch (ExecutionException | InterruptedException e) {
cancel();
} catch (TimeoutException e) {
this.timeout = true;
callback(error, null, e, false);
}
}
private void onCancel() {
if (cancel != null && cancel.first != null) cancel.first.accept(this);
onComplete();
}
private void onSuccess(V v) {
if (success != null && success.first != null) success.first.accept(this, v);
onComplete();
}
private void onError(Throwable t) {
if (error != null && error.first != null) error.first.accept(this, t);
onComplete();
}
private void callback(Pair, Executor> pair, V v, Throwable e, boolean cancel) {
if (pair == null || pair.second == null) {
if (cancel) onCancel();
else if (e != null) onError(e);
else onSuccess(v);
} else {
pair.second.execute(() -> callback(null, v, e, cancel));
}
}
private void onComplete() {
if (complete != null) {
complete.accept(this);
}
}
public boolean cancel() {
return super.cancel(true);
}
public String getTag() {
return tag;
}
public static Builder builder(Callable callable) {
return new Builder<>(callable);
}
public static final class Builder {
private Pair, V>, Executor> success;
private Pair, Throwable>, Executor> error;
private Pair>, Executor> cancel;
private Consumer> complete;
private final Callable callable;
private String tag;
public Builder(Callable callable) {
this.callable = callable;
}
public Builder tag(String tag) {
this.tag = tag;
return this;
}
public Builder success(BiConsumer, V> consumer) {
return success(null, consumer);
}
public Builder success(Executor executor, BiConsumer, V> consumer) {
success = Pair.create(consumer, executor);
return this;
}
public Builder error(BiConsumer, Throwable> consumer) {
return error(null, consumer);
}
public Builder error(Executor executor, BiConsumer, Throwable> consumer) {
error = Pair.create(consumer, executor);
return this;
}
public Builder cancel(Consumer> consumer) {
return cancel(null, consumer);
}
public Builder cancel(Executor executor, Consumer> consumer) {
cancel = Pair.create(consumer, executor);
return this;
}
public Builder complete(Consumer> consumer) {
complete = consumer;
return this;
}
public Task submit(Executor executor, long timeout) {
Task task = new Task<>(this);
executor.execute(task);
executor.execute(() -> task.get(timeout));
return task;
}
public Task submit(Executor executor) {
Task task = new Task<>(this);
executor.execute(task);
return task;
}
}
}