1.Jdk自带Future模式
类图:
从类图中可以看出,RunnableFuture接口继承了Future和Runnable接口,而FutureTask类实现了RunnableFuture接口。所以FutureTask具有Future和Runnable的所有特性。Future还关联一个Callable的实例,来定义具体的计算过程,返回计算结果。
一个Future代表了一个异步计算的结果。提供了检查该计算是否完成,等待它完成,和提取计算结果的方法。当计算完成后,结果只能使用get方法获取,直到计算结束,否则阻塞。取消由cancel方法执行。还有其他的方法用来决定这个任务是否正常完成或者被取消。
FutureTask是一个可以取消的一步计算工具。该类提供了一个基本的Future实现,拥有开始和取消计算的方法,可以查询计算是否完成,提取计算的结果。结果只有当计算完成后才能提取;get方法会阻塞如果计算还没有完成。一旦计算完成,计算不能重新开始或者取消(除非计算通过使用runAndReset调用)。一个FutureTask可以被用来包装一个Callable或者Runnable对象。因为FutureTask实现Runnable接口,一个FutureTask可以被提交到一个Executor来执行。
2.Future的使用
public class Demo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
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<>(call);
Thread thread = new Thread(task);
thread.start();
// do something else
System.out.println("干点别的...");
Integer result = task.get();
System.out.println("拿到的结果: " + result);
}
}
3.自己实现一个Future模式
public class Product {
private Integer id;
private String name;
public Product(Integer id, String name) {
System.out.println("开始生产蛋糕...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
this.id = id;
this.name = name;
System.out.println("蛋糕生产结束...");
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Product{" +
"id='" + id + '\'' +
", name='" + name + '\'' +
'}';
}
}
public class Future {
private Product product;
private boolean down = false;
public synchronized Product getProduct() {
while (!down) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return product;
}
public synchronized void setProduct(Product product) {
this.product = product;
down = true;
notifyAll();
}
}
public class ProductFactory {
public static Future createProduct(final String name) {
final Future future = new Future();
new Thread(new Runnable() {
@Override
public void run() {
Product product = new Product(new Random().nextInt(), name);
future.setProduct(product);
}
}).start();
return future;
}
}
public class FutureDemo {
public static void main(String[] args) {
Future future = ProductFactory.createProduct("蛋糕");
System.out.println("我去上班了, 下班了我来取蛋糕...");
System.out.println("我拿蛋糕回家. " + future.getProduct());
}
}