com.peterphi.std.threading.RunnableCallableFuture Maven / Gradle / Ivy
package com.peterphi.std.threading;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.Future;
import java.util.concurrent.RunnableFuture;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* A wrapper type which takes a Callable and turns it into a RunnableFuture
*
* @param
*/
public class RunnableCallableFuture extends SettableFuture implements Runnable, RunnableFuture
{
/**
* The callable to execute
*/
private final Callable callable;
/**
* Set to true once run() has been called
*/
private final AtomicBoolean started = new AtomicBoolean(false);
public RunnableCallableFuture(Callable callable)
{
if (callable == null)
throw new IllegalArgumentException("Must supply a non-null Callable!");
this.callable = callable;
}
@Override
public void run()
{
if (started.compareAndSet(false, true))
{
final T value;
try
{
value = callable.call();
}
catch (Throwable e)
{
fail(e);
return;
}
set(value);
}
}
/**
* Start a new daemon thread to call the run() method asynchronously, returning this object as a Future (and not a
* RunnableCallableFuture)
*
* @return
*/
public Future asyncRun()
{
final Thread t = new Thread(this);
{
t.setName("AsyncRun for " + this);
t.setDaemon(true);
t.start();
}
return this;
}
/**
* Runs this Callable asynchronously using the specified {@link Executor}
*
* @param executor
*
* @return
*/
public Future asyncRun(final Executor executor)
{
executor.execute(this);
return this;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
return "[RunnableCallableFuture callable=" + callable + "]";
}
/**
* Takes a Callable, executing it in the background, returning a Future to its result
* Users are advised to use a ThreadPool instead of this method.
*
* @param
* the return type
* @param callable
* the callable to return a Future to
*
* @return
*/
public static Future asyncRun(Callable callable)
{
RunnableCallableFuture future = new RunnableCallableFuture(callable);
future.asyncRun();
return future;
}
}