====== java异步回调 ====== ===== 理解 ===== 主线程有多个动作,比较耗时,如果主线程是单线程执行,会阻塞比较长时间才能完成。 异步指的是:如果多个动作是可以并行同时去做的,则可以采用多线程异步发起多个动作的调用。 回调指的是:多个动作多线程异步执行完的结果,还可以传送到主线程中,继续下面的操作。 ===== 用到的类 ===== - ExecutorService接口:定义线程池大小,执行FuruteTask - Callable接口:真正异步执行的内容,可以返回执行结果 - FuruteTask类:指定Callable对象,并在主线程中获取异步执行结果 ===== 代码示例 ===== /** * 测试AsynCallback 异步回调 * @param request * @return */ @RequestMapping(value = "/testAsynCallback",produces="application/json") public @ResponseBody String testAsynCallback() { logger.info("测试AsynCallback,开始==="); /** * 进行异步任务列表 */ List> futureTasks = new ArrayList>(); /** * 线程池 初始化3个线程 和JDBC连接池是一个意思 实现重用 */ ExecutorService executorService = Executors.newFixedThreadPool(3); long start = System.currentTimeMillis(); /** * 类似与run方法的实现 Callable是一个接口,在call中手写逻辑代码 */ Callable callable = new Callable() { @Override public Integer call() throws Exception { Integer res = new Random().nextInt(100); logger.info("call执行[" + res + "]开始!"); Thread.sleep(3000); logger.info("call执行[" + res + "]结束!"); return res; } }; logger.info("将5个任务提交到线程池开始!"); for(int i=0;i<5;i++){ /** * 创建一个异步任务 */ FutureTask futureTask = new FutureTask(callable); futureTasks.add(futureTask); /** * 提交异步任务到线程池,让线程池管理任务 * 由于是异步并行任务,所以这里并不会阻塞 * 注意:一旦提交,线程池如果有可用线程,马上分配执行! */ executorService.submit(futureTask); } logger.info("将5个任务提交到线程池结束!"); logger.info("从异步任务列表中获取所有回调开始!"); int count = 0; for (FutureTask futureTask : futureTasks) { /** * futureTask.get() 得到我们想要的结果 * 该方法有一个重载get(long timeout, TimeUnit unit) 第一个参数为最大等待时间,第二个为时间的单位 */ try { count += futureTask.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } logger.info("从异步任务列表中获取所有回调结束!"); long end = System.currentTimeMillis(); logger.info("线程池的任务全部完成:结果为:"+count+",main线程关闭,进行线程的清理"); logger.info("使用时间:"+(end-start)+"ms"); /** * 清理线程池 */ executorService.shutdown(); logger.info("测试AsynCallback,结束==="); return "testAsynCallbackOK~"; } ===== 日志输出 ===== 2017-05-18 07:16:54,068 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:165] - 测试AsynCallback,开始=== 2017-05-18 07:16:54,070 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:189] - 将5个任务提交到线程池开始! 2017-05-18 07:16:54,072 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:203] - 将5个任务提交到线程池结束! 2017-05-18 07:16:54,072 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:204] - 从异步任务列表中获取所有回调开始! 2017-05-18 07:16:54,071 [pool-1-thread-1] INFO [com.gxx.record.web.thread.ThreadController$1:183] - call执行[68]开始! 2017-05-18 07:16:54,071 [pool-1-thread-2] INFO [com.gxx.record.web.thread.ThreadController$1:183] - call执行[84]开始! 2017-05-18 07:16:54,072 [pool-1-thread-3] INFO [com.gxx.record.web.thread.ThreadController$1:183] - call执行[47]开始! 2017-05-18 07:16:57,076 [pool-1-thread-1] INFO [com.gxx.record.web.thread.ThreadController$1:185] - call执行[68]结束! 2017-05-18 07:16:57,076 [pool-1-thread-3] INFO [com.gxx.record.web.thread.ThreadController$1:185] - call执行[47]结束! 2017-05-18 07:16:57,076 [pool-1-thread-2] INFO [com.gxx.record.web.thread.ThreadController$1:185] - call执行[84]结束! 2017-05-18 07:16:57,077 [pool-1-thread-3] INFO [com.gxx.record.web.thread.ThreadController$1:183] - call执行[30]开始! 2017-05-18 07:16:57,076 [pool-1-thread-1] INFO [com.gxx.record.web.thread.ThreadController$1:183] - call执行[57]开始! 2017-05-18 07:17:00,081 [pool-1-thread-1] INFO [com.gxx.record.web.thread.ThreadController$1:185] - call执行[57]结束! 2017-05-18 07:17:00,081 [pool-1-thread-3] INFO [com.gxx.record.web.thread.ThreadController$1:185] - call执行[30]结束! 2017-05-18 07:17:00,082 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:219] - 从异步任务列表中获取所有回调结束! 2017-05-18 07:17:00,082 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:221] - 线程池的任务全部完成:结果为:286,main线程关闭,进行线程的清理 2017-05-18 07:17:00,082 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:222] - 使用时间:6013ms 2017-05-18 07:17:00,082 [http-bio-8080-exec-3] INFO [com.gxx.record.web.thread.ThreadController:228] - 测试AsynCallback,结束=== ===== 性能优化分析 ===== 主线程阻塞从3*5=15秒,优化到3*(5/3)=6秒