常州的网站建设,哪个网站可以做魔方图片,企业网站建设 邮箱,php如何创建站点在初识Future一文中介绍了Future的核心方法。本文中接着介绍如何用Future优化我们的程序性能。 在此之前#xff0c;有必要介绍Future接口的一个实现类FutureTask。
FutureTask介绍
FutureTask继承结构
首先我们看一下FutureTask的继承结构#xff1a; public class Futur…在初识Future一文中介绍了Future的核心方法。本文中接着介绍如何用Future优化我们的程序性能。 在此之前有必要介绍Future接口的一个实现类FutureTask。
FutureTask介绍
FutureTask继承结构
首先我们看一下FutureTask的继承结构 public class FutureTaskV implements RunnableFutureV{...
}public interface RunnableFutureV extends Runnable, FutureV {void run();
}
可以看出FutureTask实现了RunnableFuture接口而RunnableFuture继承了Runnable和Future也就是说FutureTask既是Runnable也是Future。所以 FutureTask 既可以作为 Runnable 被线程执行又可以作为 Future 得到 Callable 的返回值。
下面的例子展示了FutureTask的 简单 用法
class FutureTaskCallable implements Callable{Overridepublic String call() throws Exception {return Hello FutureTask;}
}public class FutureTaskExample1 {public static void main(String[] args) throws ExecutionException, InterruptedException {FutureTaskString futureTask new FutureTask(new FutureTaskCallable());Thread thread new Thread(futureTask);thread.start();System.out.println(子线程返回值: futureTask.get());}
}//输出
子线程返回值:Hello FutureTask这段程序中可以看出FutureTask类的构造函数是Callable类型在创建了FutureTask对象后然后将这个对象当作一个 Runnable 放到 new Thread() 中去执行最后再用 FutureTask 的 get 得到子线程 的 返回结果。简单介绍完FutureTask现在可以进入文章的主题了如何利用Future优化我们的程序性能。
利用Future优化程序
考虑这样一个场景小码哥突然心血来潮想练练字了但是他现在手头连一只钢笔都没有书桌也是乱糟糟的于是他打算在网购一支钢笔然后整理书桌就开始练字用代码实现这个场景
普通多线程版本
我们先来看普通的多线程版本是如何实现。
//购买钢笔任务
class BuyPenRunnable implements Runnable{private String pen;Overridepublic void run() {System.out.println(【购买钢笔】下单等待送货上门);//模拟送货时间try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(【购买钢笔】快递送到);pen 神笔;}public String getPen() {return pen;}
}public class CommomThreadExample {public static void main(String[] args) throws InterruptedException {long startTime System.currentTimeMillis();BuyPenRunnable buyPenRunnable new BuyPenRunnable();Thread buyPenThread new Thread(buyPenRunnable);buyPenThread.start();//模拟整理书桌耗时3000msSystem.out.println(【整理书桌】开始整理);Thread.sleep(3000);System.out.println(【整理书桌】整理完了);//保证笔送到buyPenThread.join();//所有准备好开始练字write(buyPenRunnable.getPen());long endTime System.currentTimeMillis();System.out.println(总共用时 (endTime - startTime) ms);}private static void write(String pen){System.out.println(【开始写字】 pen);}
}//输出
【购买钢笔】下单等待送货上门
【购买钢笔】快递送到
【整理书桌】开始整理
【整理书桌】整理完了
【开始写字】神笔
总共用时 5020 ms这里尽管将购买钢笔和整理桌子并行化了节省了时间但是这个版本有2个问题 通过 Runnable 实现任务但为了获取结果我们需要定义共享变量 pen并提供一个方法 getPen() 来获取这个变量。 任务的取消和状态检查不方便。
Future实现
利用FutureTask实现上面的功能代码如下
//购买钢笔任务
class BuyPenCallable implements Callable {Overridepublic String call() {System.out.println(【购买钢笔】下单等待送货上门);//模拟送货时间try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(【购买钢笔】快递送到);return 神笔;}
}public class FutureTaskExample {public static void main(String[] args) throws InterruptedException, ExecutionException {long startTime System.currentTimeMillis();CallableString buyPenCallable () - {System.out.println(【购买钢笔】下单等待送货上门);// 模拟送货时间try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(【购买钢笔】快递送到);return 神笔;};FutureTaskString futureTask new FutureTask(buyPenCallable);ExecutorService executor Executors.newFixedThreadPool(1);executor.submit(futureTask);// 模拟整理书桌耗时3000msSystem.out.println(【整理书桌】开始整理);Thread.sleep(3000);System.out.println(【整理书桌】整理完了);// 尝试取消任务如果需要这么做//boolean cancelled future.cancel(false); // 等待获取笔的结果String pen futureTask.get();// 所有准备好开始练字write(pen);long endTime System.currentTimeMillis();System.out.println(总共用时 (endTime - startTime) ms);executor.shutdown();}private static void write(String pen) {System.out.println(【开始写字】 pen);}
}上面的代码中可以看到FutureTask实现的实现方式 获取结果更方便通过 Callable 的 call() 方法直接返回结果不需要显式地定义共享变量和同步机制。 对线程的管理更方便FutureTask 提供了 cancel() 方法可以取消任务并通过 isCancelled() 和 isDone() 方法检查任务状态。
总结
在我们的实际项目中很多时候我们的接口需要通过rpc调用去调用其它的多个服务拿到结果聚合如果采用同步调用的方式假设一次远程调用的时间为 300ms则一个 Client 同步对三个 Server 分别进行一次 RPC 调 用的总时间需要耗费 900ms。 如果使用 Future 模式对其进行改造将同步的 RPC 调用改为异步并发的 RPC 调用一个 Client 异步并发对三个 Server 分别进行一次 RPC 调用那么正常情况下大约只需要 300ms就能拿到所有服务的数据了。Future的好处不言而喻。