All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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 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;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy