使用线程中,有时候 我们需要获取子线程执行后的返回值,这时候我们可以用到Callable接口,实现该接口重写call方法,返回一个封装后的Future对象。
Callable<Integer> subTask = new Callable<Integer>() {
@Override
public Integer call() throws Exception {
// ... 执行异步任务
int millis = (int) (Math.random() * 1000);
Thread.sleep(millis);
return millis;
}
};
// 异步调用,返回一个MyFuture对象
MyFuture<Integer> future = executor.execute(subTask);
// ... 执行其他操作
try {
// 获取异步调用的结果
Integer result = future.get();
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
利用exeute方法,对于主线来说,他不需要创建并管理子线程了,而且可以方便的获取子线程的返回结果。
execute方法具体实现,他封装了创建子线程,获取返回结果的过程,会创建一个子线程运行,其中子线程的代码:
static class ExecuteThread<V> extends Thread {
private V result = null;
private Exception exception = null;
private boolean done = false;
private Callable<V> task;
private Object lock;
public ExecuteThread(Callable<V> task, Object lock) {
this.task = task;
this.lock = lock;
}
@Override
public void run() {
try {
result = task.call();
} catch (Exception e) {
exception = e;
} finally {
synchronized (lock) {
done = true;
lock.notifyAll();
}
}
}
public V getResult() {
return result;
}
public boolean isDone() {
return done;
}
public Exception getException() {
return exception;
}
}
execute方法的代码:
public <V> MyFuture<V> execute(final Callable<V> task) {
final Object lock = new Object();
final ExecuteThread<V> thread = new ExecuteThread<>(task, lock);
//开启子线程
thread.start();
MyFuture<V> future = new MyFuture<V>() {
@Override
public V get() throws Exception {
synchronized (lock) {
//子线程如果没执行完,阻塞
while (!thread.isDone()) {
try {
lock.wait();
} catch (InterruptedException e) {
}
}
if (thread.getException() != null) {
throw thread.getException();
}
return thread.getResult();
}
}
};
return future;
}
这个子线程执行实际的子任务,记录结果到result,记录异常到exception,执行结束后设置共享变量done为true,并调用notifyAll以唤醒可能在等待的主线程。以上代码主要演示该方法基本原理,java
中有具体实现。
--------------以上内容摘于java编程的逻辑