Java设计模式之异步方法

AsyncCallback.java

/**

 * AsyncCallback interface

 */

public interface AsyncCallback {
    void onComplete(T value, Optional ex);
}

AsyncExecutor.java

/**
 * 
 * AsyncExecutor interface
 *
 */
public interface AsyncExecutor {
   AsyncResult startProcess(Callable task);

   AsyncResult startProcess(Callable task, AsyncCallback callback);

   T endProcess(AsyncResult asyncResult) throws ExecutionException, InterruptedException;
  
}

AsyncResult.java

/**
 * 
 * AsyncResult interface
 */
public interface AsyncResult {

  boolean isCompleted();

  T getValue() throws ExecutionException;

  void await() throws InterruptedException;
}

实现类:ThreadAsyncExecutor.java

/**
 * 
 * Implementation of async executor that creates a new thread for every task.
 * 
 */
public class ThreadAsyncExecutor implements AsyncExecutor {

  /** Index for thread naming */
  private final AtomicInteger idx = new AtomicInteger(0);

  @Override
  public  AsyncResult startProcess(Callable task) {
    return startProcess(task, null);
  }

  @Override
  public  AsyncResult startProcess(Callable task, AsyncCallback callback) {
    CompletableResult result = new CompletableResult<>(callback);
    new Thread(() -> {
      try {
        result.setValue(task.call());
      } catch (Exception ex) {
        result.setException(ex);
      }
    } , "executor-" + idx.incrementAndGet()).start();
    return result;
  }

  @Override
  public  T endProcess(AsyncResult asyncResult) throws ExecutionException, InterruptedException {
    if (asyncResult.isCompleted()) {
      return asyncResult.getValue();
    } else {
      asyncResult.await();
      return asyncResult.getValue();
    }
  }

  /**
   * Simple implementation of async result that allows completing it successfully with a value or exceptionally with an
   * exception. A really simplified version from its real life cousins FutureTask and CompletableFuture.
   *
   * @see java.util.concurrent.FutureTask
   * @see java.util.concurrent.CompletableFuture
   */
  private static class CompletableResult implements AsyncResult {

    static final int RUNNING = 1;
    static final int FAILED = 2;
    static final int COMPLETED = 3;

    final Object lock;
    final Optional> callback;

    volatile int state = RUNNING;
    T value;
    Exception exception;

    CompletableResult(AsyncCallback callback) {
      this.lock = new Object();
      this.callback = Optional.ofNullable(callback);
    }

    /**
     * Sets the value from successful execution and executes callback if available. Notifies any thread waiting for
     * completion.
     *
     * @param value
     *          value of the evaluated task
     */
    void setValue(T value) {
      this.value = value;
      this.state = COMPLETED;
      this.callback.ifPresent(ac -> ac.onComplete(value, Optional.empty()));
      synchronized (lock) {
        lock.notifyAll();
      }
    }

    /**
     * Sets the exception from failed execution and executes callback if available. Notifies any thread waiting for
     * completion.
     *
     * @param exception
     *          exception of the failed task
     */
    void setException(Exception exception) {
      this.exception = exception;
      this.state = FAILED;
      this.callback.ifPresent(ac -> ac.onComplete(null, Optional.of(exception)));
      synchronized (lock) {
        lock.notifyAll();
      }
    }

    @Override
    public boolean isCompleted() {
      return state > RUNNING;
    }

    @Override
    public T getValue() throws ExecutionException {
      if (state == COMPLETED) {
        return value;
      } else if (state == FAILED) {
        throw new ExecutionException(exception);
      } else {
        throw new IllegalStateException("Execution not completed yet");
      }
    }

    @Override
    public void await() throws InterruptedException {
      synchronized (lock) {
        if (!isCompleted()) {
          lock.wait();
        }
      }
    }
  }
}

App.java

public class App {

  /**
   * Program entry point
   */
  public static void main(String[] args) throws Exception {
    // construct a new executor that will run async tasks
    AsyncExecutor executor = new ThreadAsyncExecutor();

    // start few async tasks with varying processing times, two last with callback handlers
    AsyncResult asyncResult1 = executor.startProcess(lazyval(10, 500));
    AsyncResult asyncResult2 = executor.startProcess(lazyval("test", 300));
    AsyncResult asyncResult3 = executor.startProcess(lazyval(50L, 700));
    AsyncResult asyncResult4 = executor.startProcess(lazyval(20, 400), callback("Callback result 4"));
    AsyncResult asyncResult5 = executor.startProcess(lazyval("callback", 600), callback("Callback result 5"));

    // emulate processing in the current thread while async tasks are running in their own threads
    Thread.sleep(350); // Oh boy I'm working hard here
    log("Some hard work done");

    // wait for completion of the tasks
    Integer result1 = executor.endProcess(asyncResult1);
    String result2 = executor.endProcess(asyncResult2);
    Long result3 = executor.endProcess(asyncResult3);
    asyncResult4.await();
    asyncResult5.await();

    // log the results of the tasks, callbacks log immediately when complete
    log("Result 1: " + result1);
    log("Result 2: " + result2);
    log("Result 3: " + result3);
  }

 
  private static  Callable lazyval(T value, long delayMillis) {
    return () -> {
      Thread.sleep(delayMillis);
      log("Task completed with: " + value);
      return value;
    };
  }

  private static  AsyncCallback callback(String name) {
    return (value, ex) -> {
      if (ex.isPresent()) {
        log(name + " failed: " + ex.map(Exception::getMessage).orElse(""));
      } else {
        log(name + ": " + value);
      }
    };
  }

  private static void log(String msg) {
    System.out.println(String.format("[%1$-10s] - %2$s", Thread.currentThread().getName(), msg));
  }
}

你可能感兴趣的:(Java设计模式之异步方法)