/* * ==================================================================== Licensed to the Apache Software Foundation (ASF) * under one or more contributor license agreements. See the NOTICE file distributed with this work for additional * information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the * License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * ==================================================================== * * This software consists of voluntary contributions made by many individuals on behalf of the Apache Software * Foundation. For more information on the Apache Software Foundation, please see <http://www.apache.org/>. * */ package org.springside.modules.utils.concurrent; import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.commons.lang3.Validate; /** * 从Apache HttpClient 4.2 移植,一个Future实现类的基本框架. */ public abstract class BasicFuture<T> implements Future<T> { private volatile boolean completed; private volatile boolean cancelled; private volatile T result; private volatile Exception ex; @Override public boolean isCancelled() { return this.cancelled; } @Override public boolean isDone() { return this.completed; } @Override public synchronized T get() throws InterruptedException, ExecutionException { while (!this.completed) { wait(); } return getResult(); } @Override public synchronized T get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { Validate.notNull(unit, "Time unit"); final long msecs = unit.toMillis(timeout); final long startTime = (msecs <= 0) ? 0 : System.currentTimeMillis(); long waitTime = msecs; if (this.completed) { return getResult(); } else if (waitTime <= 0) { throw new TimeoutException(); } else { for (;;) { wait(waitTime); if (this.completed) { return getResult(); } else { waitTime = msecs - (System.currentTimeMillis() - startTime); if (waitTime <= 0) { throw new TimeoutException(); } } } } } private T getResult() throws ExecutionException { if (this.ex != null) { throw new ExecutionException(this.ex); } return this.result; } public boolean completed(final T result) { synchronized (this) { if (this.completed) { return false; } this.completed = true; this.result = result; notifyAll(); } onCompleted(result); return true; } public boolean failed(final Exception exception) { synchronized (this) { if (this.completed) { return false; } this.completed = true; this.ex = exception; notifyAll(); } onFailed(exception); return true; } @Override public boolean cancel(final boolean mayInterruptIfRunning) { synchronized (this) { if (this.completed) { return false; } this.completed = true; this.cancelled = true; notifyAll(); } onCancelled(); return true; } protected abstract void onCompleted(T result); protected abstract void onFailed(Exception ex); protected abstract void onCancelled(); }