#StackBounty: #java #concurrency #wrapper FutureTaskWrapper for Java

Bounty: 100

I did not like that get synchronizes every time I call it – because I may be calling it more than once. So I wrote the wrapper for the future interface which keeps not synchronized local variable for completion state and caches the result. I am very sure it is thread safe.
Please have a look:

package i;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

public class FutureTaskWrapper<V> implements RunnableFuture<V> {

    private FutureTask<V> localFuture;
    private V result;
    //this one is not synchronized on purpose. It does not have to be.
    //It will either use wrapped class' done mechanism or eventually will     update and it will use cached result.
    private boolean done = false;


    public FutureTaskWrapper(FutureTask<V> instance) {
        localFuture = instance;
    }

    @Override
    public void run() {
        localFuture.run();
    }

    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return localFuture.cancel(mayInterruptIfRunning);
    }

    @Override
    public boolean isCancelled() {
        return localFuture.isCancelled();
    }

    @Override
    public boolean isDone() {
        if (done) {
            return true;
        } else {
            return localFuture.isDone();
        }
    }

    @Override
    public V get() throws InterruptedException, ExecutionException {
        if (done) {
            System.out.println("using cached version.");
            return result;
        } else {
            System.out.println("using version version from future.");
            result = localFuture.get();
            done = true;
            return result;
        }
    }

    @Override
    public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
        if (done) {
            System.out.println("using cached version.");
            return result;
        } else {
            System.out.println("using version version from future.");
            result = localFuture.get(timeout, unit);
            //could clean up localFuture here.
            done = true;
            return result;
        }
    }

    //main method for testing.
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ExecutorService executor = Executors.newCachedThreadPool();
        FutureTask<String> future = new FutureTask<>(() -> {
            Thread.sleep(1000L);
            return "future";
        });
        FutureTaskWrapper<String> wrapper = new FutureTaskWrapper(future);
        executor.submit(future);
        wrapper.get();
        wrapper.get();
        wrapper.get();
        wrapper.get();

        executor.shutdownNow();
    }
}


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.