昨天头儿给的学习文档我还没看完,头儿说:“MongoDB光会简单的添删改查什么的不行,要深入了解,你们连$set和$inc使用场景都分不清。”

  确实,学习过一年多SQL,确实对学习MongoDB有点影响。

  不过,今天数据库的事情先翻过去,因为我在学习文档中还看到了另外一个加大加粗的标题——异步编程

  Java在Java8之前貌似(因为我也刚学,所以不对还请各位前辈指正)没有真正实现异步编程的方法,当时异步编程会使用回调或者使用其他的框架(如Netty和Guava)来实现。后来Java8借鉴了很多框架的思想,可以借助JDK原生的CompletableFuture来实现异步操作,而且用Lambda表达式来写匿名内部类大大简化了代码量。

  那么,异步编程到底是用来干什么的呢?

  试想这样的场景——老爸有俩孩子:小红和小明。老爸想喝酒了,他让小红去买酒,小红出去了。然后老爸突然想吸烟了,于是老爸让小明去买烟。在面对对象的思想中,一般会把买东西,然后买回来这件事作为一个方法,如果按照顺序结构或者使用多线程同步的话,小明想去买烟就必须等小红这个买东西的操作进行完。这样无疑增加了时间的开销。异步就是为了解决这样的问题。你可以分别给小红小明下达指令,让他们去买东西,然后你就可以自己做自己的事,等他们买回来的时候接收结果就可以了。

  所以,为了尽快学习异步操作,我使用Java8的方法编写了这样一段代码来帮助了解:

 package com.liumaowu;

 import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; public class TestFuture {
public static void main(String[] args) {
//两个线程的线程池
ExecutorService executor= Executors.newFixedThreadPool(2);
//小红买酒任务,这里的future2代表的是小红未来发生的操作,返回小红买东西这个操作的结果
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(()-> {
System.out.println("爸:小红你去买瓶酒!");
try {
System.out.println("小红出去买酒了,女孩子跑的比较慢,估计5s后才会回来...");
Thread.sleep(5000);
return "我买回来了!";
} catch (InterruptedException e) {
System.err.println("小红路上遭遇了不测");
return "来世再见!";
}
},executor); //小明买烟任务,这里的future1代表的是小明未来买东西会发生的事,返回值是小明买东西的结果
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(()->{
System.out.println("爸:小明你去买包烟!");
try {
System.out.println("小明出去买烟了,可能要3s后回来...");
Thread.sleep(3000);
return "我买回来了!";
} catch (InterruptedException e) {
System.out.println("小明路上遭遇了不测!");
return "这是我托人带来的口信,我已经不在了。";
}
},executor); //获取小红买酒结果,从小红的操作中获取结果,把结果打印
future2.thenAccept((e)->{System.out.println("小红说:"+e);});
//获取小明买烟的结果
future1.thenAccept((e)->{System.out.println("小明说:"+e);}); System.out.println("爸:loading......");
System.out.println("爸:我觉得无聊甚至去了趟厕所。");
System.out.println("爸:loading......");
}
}

  这个运行结果如下:

爸:小红你去买瓶酒!
小红出去买酒了,女孩子跑的比较慢,估计5s后才会回来...
爸:小明你去买包烟!
小明出去买烟了,可能要3s后回来...
爸:loading......
爸:我觉得无聊甚至去了趟厕所。
爸:loading......
小明说:我买回来了!
小红说:我买回来了!

  因为sleep时间调的挺大,所以可以很明显的看到小明买回来的结果是在等待之后一会儿才跳出来,小红买回来的结果也等待了一会儿才跳出来。因为是先让小红买,再让小明出去的,但是小明的结果先回来,这说明什么时候取到结果取决于操作的时间长度。

  之后我把取futrue的结果的操作放到了老爸等待语句的下面,如下:

 /*
上面的代码不动
*/
System.out.println("爸:loading......");
System.out.println("爸:我觉得无聊甚至去了趟厕所。");
System.out.println("爸:loading......");
//获取小红买酒结果
future2.thenAccept((e)->{System.out.println("小红说:"+e);});
//获取小明买烟的结果
future1.thenAccept((e)->{System.out.println("小明说:"+e);});

  多次运行之后结果就比较有意思了:

结果1:

结果2:

结果3

  这种解决异步的方式还是使用到了多线程,在获取结果之前,操作的顺序取决于线程操作到了哪一步,比如结果2,因为小红线程启动的慢了,所以小明先出去了。但是如果先取结果的话,会确保这个线程已经启动了,所以老爸loading始终显示在老爸发出买东西命令之后。这也算先强制线程启动,再进行主操作。

  (补充:可能因为更换了电脑,性能有所提高,导致再次试验这段代码的时候只出现结果一。但是爸爸的loading代码出现在小明执行动作的前面已经可以解释,这段异步代码的执行时间取决于线程的启动速度和执行。)

在看了异步之后,不可避免地会把同步/异步/多线程弄混淆,那么我们再来总结下几个东西的区别

一般情况:顺序结构,必须等待前面的操作完成(两个人说话,a把所有话说完,b才能继续说)

并发:同一时间段处理多个任务的能力(两人说话,支持你一言我一语的交流,两人在一个时间段内都有说话,是基于时间段内的同时发生)

并发又有同步和互斥

  互斥:不能同时使用临界资源(有一个共享资源--话筒,两人必须用话筒说话,但同时只能有一个人用这个话筒,保证了只有一个人在说话)

  同步:前一个处理的结果作为下一个处理的资源。大多数情况下,同步已经实现了互斥。(两人你一言我一语的交流,我必须知道你说了啥我才能接上你的话)

并行:同一时刻处理多个任务的能力(两人合唱,同时出声)

异步:不用等待一个结果出来,可以继续其他操作(两个人不说话了,寄信,a把信拿到邮局就不用管了,回家可以想干嘛就干嘛,等b回信到了,取邮局接收一下结果--b的回信就可以了)

多线程:如果说同步和异步是对如何处理事情的要求,那么多线程就是实现这些要求的方法

  

Java 异步编程的更多相关文章

  1. Paip.Php Java 异步编程。推模型与拉模型。响应式(Reactive)”编程FutureData总结... 1

    Paip.Php  Java 异步编程.推模型与拉模型.响应式(Reactive)"编程FutureData总结... 1.1.1       异步调用的实现以及角色(:调用者 提货单) F ...

  2. java异步编程降低延迟

    目录 java异步编程降低延迟 一.ExecutorService和CompletionService 二.CompletableFuture(重要) 三.stream中的parallel(并行流) ...

  3. Java 异步编程 (5 种异步实现方式详解)

    ​ 同步操作如果遇到一个耗时的方法,需要阻塞等待,那么我们有没有办法解决呢?让它异步执行,下面我会详解异步及实现@mikechen 目录 什么是异步? 一.线程异步 二.Future异步 三.Comp ...

  4. Java异步编程——深入源码分析FutureTask

    Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...

  5. Java 异步编程的几种方式

    前言 异步编程是让程序并发运行的一种手段.它允许多个事情同时发生,当程序调用需要长时间运行的方法时,它不会阻塞当前的执行流程,程序可以继续运行,当方法执行完成时通知给主线程根据需要获取其执行结果或者失 ...

  6. java异步编程

    异步编程提供了一个非阻塞事件驱动的模型.通过异步消除阻塞,可以让web服务响应更多请求.可以让系统更高效的执行.比如log框架,记录日志或异常时异步执行可避免影响正常业务流程的执行. 异步变成如何把线 ...

  7. java并发系列(八)-----java异步编程

    同步计算与异步计算 从多个任务的角度来看,任务是可以串行执行的,也可以是并发执行的.从单个任务的角度来看,任务的执行方式可以是同步的,也可以是异步的. Runnable.Callable.Future ...

  8. Java异步编程第2篇

    假如如今有一个Buttonbutton,Buttonbutton上有click和doubleclick事件. 两个不同的事件须要进行不同的处理.这时候就须要为对应的事件注冊Listener了.改动后的 ...

  9. Atitit.异步编程 java .net php python js 对照

    Atitit.异步编程 java .net php python js 的比較 1. 1.异步任务,异步模式,  APM模式,,  EAP模式, TAP 1 1.1.       APM模式: Beg ...

随机推荐

  1. [CF1051F] Shortest Statement

    问题描述 You are given a weighed undirected connected graph, consisting of n vertices and m edges. You s ...

  2. UVA 315 :Network (无向图求割顶)

    题目链接 题意:求所给无向图中一共有多少个割顶 用的lrj训练指南P314的模板 #include<bits/stdc++.h> using namespace std; typedef ...

  3. A1065

    判断两数相加是否大于第三数,大于输出true,否则输出false(相等也是false) 1 需要注意数字溢出的问题: 2 先判断溢出,因为在a,b都是负数最小值的情况下,相加直接是正数,在c较小的时候 ...

  4. linux运维、架构之路-实时同步方案

    一.inotify+rsync实时同步 1.介绍         inotify-tools是一种强大的.细粒度的.异步的文件系统事件监控机制,可以用来监控文件系统的事件.inotify-tools是 ...

  5. React Native 之项目的启动

    运行项目有两种方法 1. 到根目录,执行 react-native run-ios 命令 会开启一个本地服务,加载jsbundle文件,然后是去index.js文件 import {AppRegist ...

  6. mysql IN操作符 语法

    mysql IN操作符 语法 作用:在 WHERE 子句中规定多个值.深圳大理石平台 语法:SELECT column_name(s) FROM table_name WHERE column_nam ...

  7. 【MySQL】 知识点记录

    0. 定位和排查问题的常用语句 查询 正在执行的事务(这个输出有事物状态表明是否等待锁):SELECT * FROM information_schema.INNODB_TRX 查看正在锁的事务:SE ...

  8. mktime夏令时处理

    https://www.cnblogs.com/dongzhiquan/archive/2011/11/05/2237075.html 我们的最终目的是把字符串格式的时间转换为内部使用的“日历时间”, ...

  9. 《SQL Server 2012 T-SQL基础》读书笔记 - 8.数据修改

    Chapter 8 Data Modification SQL Server 2008开始,支持一个语句中插入多行: INSERT INTO dbo.Orders (orderid, orderdat ...

  10. 利用Javascript解决HTML大数据列表引起的网页加载慢/卡死问题。

    在一些网页应用中,有时会碰到一个超级巨大的列表,成千上万行,这时大部份浏览器解析起来就非常痛苦了(有可能直接卡死). 也许你们会说可以分页或动态加载啊?但是有可能需求不允许分页,动态加载?网络的延迟也 ...