异步执行任务,处理其他的事情,然后获取返回结果。
案例:异步去做蛋糕,然后去做其他事情,做完其他事情然后去取蛋糕。
public static void main(String[] args) throws InterruptedException,
ExecutionException {
Callable<Integer> call = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
System.out.println("正在做蛋糕");
Thread.sleep(3000);
return 1;
}
};
FutureTask<Integer> task = new FutureTask<Integer>(call);
Thread thread = new Thread(task);
thread.start();
// do something
System.out.println(" 干点别的。。。");
// 去取蛋糕
Integer result = task.get();
System.out.println("拿到的结果为:" + result);
}
案例:
@Test
public void testFuture02() {
List<Future> lstFuture = new ArrayList<>();
lstFuture.add(executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(5000);
return 1;
}
}));
lstFuture.add(executorService.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
Thread.sleep(1000);
return 0;
}
}));
for (int i = 0; i < lstFuture.size(); i++) {
Future future = lstFuture.get(i);
if (future.isDone()) {
try {
new Thread();
logger.info("返回结果:{}", future.get());
} catch (InterruptedException e) {
logger.error("执行的任务被打断,异常信息{}",e);
} catch (ExecutionException e) {
logger.error("任务执行时出现异常,异常信息{}",e);
}
continue;
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
i--;
}
}
}
添加两个任务到线程池中执行,主线程去获取执行结果。
源码解析
public void run() {
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
setException(ex);
}
if (ran)
//CAS设置执行的状态由NEW改为COMPLETING,设置结果后,改为NORMAL状态
//唤醒链表中的每一个线程
set(result);
}
} finally {
// runner must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null;
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}
get
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
//任务还没执行完成,当前线程构造一个等待节点,添加到的链表的末尾。
s = awaitDone(false, 0L);
return report(s);
}
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for (;;) {
if (Thread.interrupted()) {
//等待线程设置了中断标识,从链表中移除
removeWaiter(q);
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {
//已经执行完成
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING) // cannot time out yet
//马上执行完成,让CPU重新调度一下,
Thread.yield();
else if (q == null)
//构造等待节点
q = new WaitNode();
else if (!queued)
//没有入链表中
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) {
//超时处理
nanos = deadline - System.nanoTime();
if (nanos <= 0L) {
removeWaiter(q);
return state;
}
LockSupport.parkNanos(this, nanos);
}
else
LockSupport.park(this);
}
}
去除已经放弃的节点
private void removeWaiter(WaitNode node) {
if (node != null) {
// 线程指向空
node.thread = null;
retry:
for (;;) { // restart on removeWaiter race
for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
s = q.next;
,
if (q.thread != null)
pred = q;
else if (pred != null) {
//如果当前节点q线程指向为空,说明已经被放弃,并且前面有节点,
//当前节点q抛弃
pred.next = s;
if (pred.thread == null) // check for race
//前面节点也线程置为空,那么就重新开始检测。
continue retry;
}
// 前面不存在节点,当前节点已经放弃,那么将头节点设置为s。
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
q, s))
//重新开始检测。
continue retry;
}
break;
}
}
}
ExecutorCompletionService
public static <T> List<T> getCompletionServiceResult(Executor executor, List<Callable<T>> callableList, long totalTimeOutMillisSecond,
long singleTimeOutMillsSecond) {
long beginTime = System.currentTimeMillis();
logger.info("提交任务个数{}", callableList.size());
CompletionService<T> completionService = new ExecutorCompletionService<>(executor);
List<Future<T>> futureList = new ArrayList<>(callableList.size());
List<T> resultList = new ArrayList<>();
try {
for (Callable<T> callable : callableList) {
futureList.add(completionService.submit(callable));
}
long endTime = System.currentTimeMillis() + totalTimeOutMillisSecond;
for (int i = 0; i < callableList.size(); ++i) {
try {
if (endTime < System.currentTimeMillis()) {
//已经超时,直接快速获取
logger.warn("全局时间已经超时");
Future<T> future = completionService.poll();
if (future == null) {
logger.warn("超时获取为空,放弃后面任务");
//放弃后面超时的
break;
} else {
resultList.add(future.get());
}
} else {
//正常获取
Future<T> future = completionService.poll(singleTimeOutMillsSecond, TimeUnit.MILLISECONDS);
if (future != null) {
resultList.add(future.get());
} else {
logger.error("获取结果超时");
}
}
} catch (Exception e) {
logger.error("任务执行异常", e);
}
}
} finally {
for (Future<T> future : futureList) {
future.cancel(true);
}
}
logger.info("提交任务耗时{}秒", (System.currentTimeMillis() - beginTime) / 1000);
return resultList;
}
ExecutorCompletionService里面维持一个队列,线程池中的任务执行完了就存放到队列中。主要是在done方法中。
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}