题目案例
已知一个业务查询操作涉及 3 个 RPC 服务调用 : query1, query2, query3, 其中query1 耗时约 1 秒, query2 耗时约 0.5 秒,query3 耗时约 0.6 秒,且query3查询条件依赖 query2 的查询结果.请编写代码,使该业务查询总体耗时最小:
考察点 1:异步
考察点 2:多线程并发控制
解题思路:
主要考察知识点异步和多线程控制。
如果采用串行执行,query1+query2+query3 总耗时为 2.1 秒。
采用多线程异步并行执行,使用线程 A 请求 query1,同时使用线程 B 请求query2后再请求 query3(query3 依赖 query2 结果只能串行执行),这样总耗时是 min(1, 0.5+0.6) = 1.1 秒。
需要熟悉 join, CountDownLatch 等线程协调控制方法,如果考生使用线程池则更佳
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
| public void queryTest1(){ ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5, true), new ThreadPoolExecutor.CallerRunsPolicy()); long start = System.currentTimeMillis();
Thread thread1 = new Thread(() -> { query1(); }); Thread thread2 = new Thread(() -> { query2(); }); Thread thread3 = new Thread(() -> { query3(); });
thread1.start(); thread2.start(); try { thread2.join(); } catch (InterruptedException e) { e.printStackTrace(); } thread3.start(); try { thread3.join(); } catch (InterruptedException e) { e.printStackTrace(); }
long time = System.currentTimeMillis() - start; System.out.println("耗时 " + time); poolExecutor.shutdown(); }
public void queryTest(){ ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(2, 10, 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5, true), new ThreadPoolExecutor.CallerRunsPolicy()); CountDownLatch downLatch = new CountDownLatch(1); CountDownLatch mainLatch = new CountDownLatch(3); long start = System.currentTimeMillis();
poolExecutor.execute(() -> { query1(); mainLatch.countDown(); });
poolExecutor.execute(() -> { query2(); downLatch.countDown(); mainLatch.countDown(); });
poolExecutor.execute(() -> { try { downLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } query3(); mainLatch.countDown(); });
try { mainLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } long time = System.currentTimeMillis() - start; System.out.println("耗时 " + time); poolExecutor.shutdown(); }
public void query1(){ System.out.println(DateUtil.date().toString("yyyy-MM-dd HH:mm:sss ") + Thread.currentThread().getName() + "query1"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } } public void query2(){ System.out.println(DateUtil.date().toString("yyyy-MM-dd HH:mm:sss ") + Thread.currentThread().getName() + "query2"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } public void query3(){ System.out.println(DateUtil.date().toString("yyyy-MM-dd HH:mm:sss ") + Thread.currentThread().getName() + "query3"); try { Thread.sleep(6000); } catch (InterruptedException e) { e.printStackTrace(); } }
|