简体   繁体   中英

FutureTask with Callable that references the FutureTask

I have a situation where I need to create a FutureTask with a Callable that checks if it's owner has been cancelled. The code I have looks like this:

public static FutureTask<Result> makeFuture(final Call call, final TaskCompletionCallback completion) {
    return new FutureTask<Result>(new Callable<Result>() {
        @Override
        public Result call() throws Exception {
            Result result = CYLib.doNetworkRequest(call, new CarryOnCallback() {
                @Override
                public boolean shouldCarryOn() {
                    return !FutureTask.isDone();
                }
            });
            return result;
        }
    });
}

Basically the doNetworkRequest asks the CarryOnCallback if it should continue at certain times during the operation. I would like for this callback to see if the FutureTask that is calling the doNetworkRequest was cancelled, which involves querying the actual FutureTask object.

Now I know that you can't really access 'this' because it hasn't been constructed yet. But is there a way around this, or a better design for my situation?

Cheers

EDIT:

Ok so I'm going about it like this now. Made a custom Callable and FutureTask. The Callable holds a reference to the FutureTask and this can be set manually after creating a new Callable:

public static MyTask makeMyTask(final Call call, final TaskCompletionCallback completion) {
    MyTask task = null;
    MyTask.InnerCallable innerCallable = new MyTask.InnerCallable(call, completion);
    task = new MyTask(innerCallable);
    innerCallable.setParent(task);
    return task;
}

And just for reference, the InnerCallable looks like this:

public static class MyTask extends FutureTask<Result> {

    InnerCallable callable;

    public MyTask(InnerCallable callable) {
        super(callable);
        this.callable = callable;
    }

    private static class InnerCallable implements Callable<Result> {

        private final Call call;
        private final TaskCompletionCallback completion;
        private WeakReference<MyTask> parentTask;

        InnerCallable(Call call, TaskCompletionCallback completion) {
            this.call = call;
            this.completion = completion;
        }

        @Override
        public Result call() {
            Result result = CYLib.doNetworkRequest(this.call, new CarryOnCallback() {
                @Override
                public boolean shouldCarryOn() {
                    MyTask task = parentTask.get();
                    return !(task == null || task.isCancelled());
                }
            });

            return result;
        }

        private void setParent(MyTask parentTask) {
            this.parentTask = new WeakReference<MyTask>(parentTask);
        }
    }
}

So, your CYLib.doNetworkRequest() is working in another thread?

private static Map<Call,FutureTask> map=new HashMap();

public static FutureTask<Result> makeFuture(final Call call, final TaskCompletionCallback completion) {
    FutureTask<Result> futureResult = new FutureTask<Result>(new Callable<Result>() {
        @Override
        public Result call() throws Exception {
            Result result = CYLib.doNetworkRequest(call, new CarryOnCallback() {
                @Override
                public boolean shouldCarryOn() {
                    return !map.get(call).isCancelled();
                }
            });
            return result;
        }
    });
    map.put(call,futureResult);
    return futureResult;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM