首页 / JAVA / java 多线程 合并多个查询结果
java 多线程 合并多个查询结果
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了java 多线程 合并多个查询结果,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4783字,纯文字阅读大概需要7分钟。
内容图文
场景:假如你突然想做饭,但是没有厨具,也没有食材。网上购买厨具比较方便,食材去超市买更放心。
实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材。所以,在主线程里面另起一个子线程去网购厨具。
但是,子线程执行的结果是要返回厨具的,而run方法是没有返回值的。所以,这才是难点,需要好好考虑一下。
模拟代码:
1 package test; 2 3 import java.util.concurrent.Callable; 4 import java.util.concurrent.ExecutionException; 5 import java.util.concurrent.FutureTask; 6 7 public class FutureCook { 8 9 public static void main(String[] args) throws InterruptedException, ExecutionException { 10 long startTime = System.currentTimeMillis(); 11 // 第一步 网购厨具 12 Callable<Chuju> onlineShopping = new Callable<Chuju>() { 13 14 @Override 15 public Chuju call() throws Exception { 16 System.out.println("第一步:下单"); 17 System.out.println("第一步:等待送货"); 18 Thread.sleep(5000); // 模拟送货时间 19 System.out.println("第一步:快递送到"); 20 return new Chuju(); 21 } 22 23 }; 24 FutureTask<Chuju> task = new FutureTask<Chuju>(onlineShopping); 25 new Thread(task).start(); 26 // 第二步 去超市购买食材 27 Thread.sleep(2000); // 模拟购买食材时间 28 Shicai shicai = new Shicai(); 29 System.out.println("第二步:食材到位"); 30 // 第三步 用厨具烹饪食材 31 if (!task.isDone()) { // 联系快递员,询问是否到货 32 System.out.println("第三步:厨具还没到,心情好就等着(心情不好就调用cancel方法取消订单)"); 33 } 34 Chuju chuju = task.get(); 35 System.out.println("第三步:厨具到位,开始展现厨艺"); 36 cook(chuju, shicai); 37 38 System.out.println("总共用时" + (System.currentTimeMillis() - startTime) + "ms"); 39 } 40 41 // 用厨具烹饪食材 42 static void cook(Chuju chuju, Shicai shicai) {} 43 44 // 厨具类 45 static class Chuju {} 46 47 // 食材类 48 static class Shicai {} 49 50 }
结果
1 第一步:下单 2 第一步:等待送货 3 第二步:食材到位 4 第三步:厨具还没到,心情好就等着(心情不好就调用cancel方法取消订单) 5 第一步:快递送到 6 第三步:厨具到位,开始展现厨艺 7 总共用时5005ms
下面具体分析一下这段代码:
1)把耗时的网购厨具逻辑,封装到了一个Callable的call方法里面。
public interface Callable<V> { /** * Computes a result, or throws an exception if unable to do so. * * @return computed result * @throws Exception if unable to compute a result */ V call() throws Exception; }
Callable接口可以看作是Runnable接口的补充,call方法带有返回值,并且可以抛出异常。
2)把Callable实例当作参数,生成一个FutureTask的对象,然后把这个对象当作一个Runnable,作为参数另起线程。
public class FutureTask<V> implements RunnableFuture<V>
public interface RunnableFuture<V> extends Runnable, Future<V>
public interface Future<V> { boolean cancel(boolean mayInterruptIfRunning); boolean isCancelled(); boolean isDone(); V get() throws InterruptedException, ExecutionException; V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException; }
这个继承体系中的核心接口是Future。Future的核心思想是:一个方法f,计算过程可能非常耗时,等待f返回,显然不明智。可以在调用f的时候,立马返回一个Future,可以通过Future这个数据结构去控制方法f的计算过程。
这里的控制包括:
get方法:获取计算结果(如果还没计算完,也是必须等待的)
cancel方法:还没计算完,可以取消计算过程
isDone方法:判断是否计算完
isCancelled方法:判断计算是否被取消
这些接口的设计很完美,FutureTask的实现注定不会简单,后面再说。
3)在第三步里面,调用了isDone方法查看状态,然后直接调用task.get方法获取厨具,不过这时还没送到,所以还是会等待3秒。对比第一段代码的执行结果,这里我们节省了2秒。这是因为在快递员送货期间,我们去超市购买食材,这两件事在同一时间段内异步执行!!!
JDK8 中 CompletableFuture 是非常强大的 Future 的扩展功能。
模拟代码:
1 CompletableFuture<List<Map<String, Object>>> bookFuture = CompletableFuture.supplyAsync(() -> bookDao.getTidb(a.getAccId())); 2 3 CompletableFuture<List<Map<String, Object>>> tableFuture = CompletableFuture.supplyAsync(() -> tableDao.findTidb(a.getAccId()); 4 5 CompletableFuture.allOf(bookFuture, tableFuture).join(); 6 7 List<Map<String, Object>> bookList = bookFuture.get(); 8 List<Map<String, Object>> tableList = tableFuture.get();
allOf 工厂方法接收一个由CompletableFuture 构成的数组,数组中的所有 Completable-Future 对象执行完成之后,它返回一个 CompletableFuture<Void> 对象。这意味着,如果你需要等待多个 CompletableFuture 对象执行完毕,对 allOf 方法返回的
CompletableFuture 执行 join 操作可以等待CompletableFuture执行完成。
或者你可能希望只要 CompletableFuture 对象数组中有任何一个执行完毕就不再等待,在这种情况下,你可以使用一个类似的工厂方法 anyOf 。
内容总结
以上是互联网集市为您收集整理的java 多线程 合并多个查询结果全部内容,希望文章能够帮你解决java 多线程 合并多个查询结果所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。