Runnable
より堅牢なスレッド アーキテクチャを提供するために、基本的なインターフェイスを拡張するフレームワークを作成することで、同様のことを行いました。後で、これが GWT の非同期コードと同様の目的で驚くほど似ていることを発見しました。
これは記憶によるものですが、基本的には次のようになります。
public interface AsyncRunnable<T> extends Runnable
{
AsyncCallback<T> getCallback();
T runAsync();
}
public interface AsyncCallback<T>
{
void onSuccess(T data);
void onFailure(Exception exception);
}
public interface AsyncCallbackInvoker<T> extends Runnable
{
// implies requirement for callback...
AsyncCallback<T> getCallback();
}
public class SuccessfulAsyncCallbackInvoker<T> implements AsyncCallback<T>
{
private final AsyncCallback<T> callback;
private final T data;
public SuccessfulAsyncCallbackInvoker(AsyncCallback<T> callback, T data)
{
// note: data being null may be valid; callback would not be
this.callback = callback;
this.data = data;
}
@Override
public void run()
{
callback.onSuccess(data);
}
@Override
public AsyncCallback<T> getCallback()
{
return callback;
}
}
public class FailureAsyncCallbackInvoker<T> implements AsyncCallback<T>
{
private final AsyncCallback<T> callback;
private final Exception exception;
public FailureAsyncCallbackInvoker(AsyncCallback<T> callback, Exception exception)
{
// note: data being null may be valid; callback would not be
this.callback = callback;
this.exception= exception;
}
@Override
public void run()
{
callback.onFailure(exception);
}
@Override
public AsyncCallback<T> getCallback()
{
return callback;
}
}
public abstract class AbstractAsyncRunnable<T> implements AsyncRunnable<T>
{
private final AsyncCallback<T> callback;
public AbstractAsyncRunnable(AsyncCallback<T> callback)
{
// if == null -> throw
this.callback = callback;
}
@Override
public /* final */ void run()
{
AsyncCallbackInvoker<T> invoker;
try
{
T data = runAsync();
invoker = new SuccessfulAsyncCallbackInvoker<T>(callback, data);
}
catch (Exception e)
{
invoker = new FailureAsyncCallbackInvoker<T>(callback, e);
}
invokeCallback(invoker);
}
// allows overriding to put callback on whatever Thread you want
protected void invokeCallback(AsyncCallbackInvoker<T> invoker)
{
invoker.run();
}
}
実際には、それは信じられないほど堅牢であることが証明されており、特にオーバーライド機能を提供することで、invokeCallback
応答が保証された多くのスレッドセーフ操作を活用できるようになりました。
runAsync
実際には、実装はメソッドをオーバーライドして、適切と思われるAsyncRunnable
ものを提供するだけで済みますAsyncCallback
。単純に完了をマークする手段として実際に使用する場合があり、そのような場合T
はVoid
(使用する場合はreturn null
from runAsync
) になる可能性があることに注意することが重要です。