同步
也就是程序从上往下
实现执行;
异步
从新开启一个新分支
,相互不会影响;
站在Http协议上分析同步与异步区别:
我们的Http
协议请求默认
情况下同步
形式调用,如果调用过程非常耗时
的情况下 客户端等待时间就非常长
, 这这种形式我们可以理解阻塞
式;
解决
办法:耗时的代码我们可以使用多线程
实现处理 后者mq
,但是不能立马获取结果; 客户端
可以主动查询
启动类上加上 @EnableAsync
异步方法加上 @Async
@RequestMapping("/getMember")
public String getMember() {
System.out.println("执行代码1");
String member = memberService.getMember(); //异步方法
System.out.println("执行代码4");
return member == null ? "程序已经在执行,请稍后主动查询" : member;
//相当于对我们每次请求使用id记录 前端在使用ajax 实现轮训主动查询结果
}
@Async
public String getMember() {
try {
System.out.println("执行代码2");
Thread.sleep(3000);
System.out.println("执行代码3");
} catch (Exception e) {
}
return "success";
}
@SpringBootApplication
@EnableAsync
public class AppSpringBoot {
public static void main(String[] args) {
SpringApplication.run(AppSpringBoot.class);
}
}
Bio是一个阻塞式的io
,不能够支持并发请求访问;可以多线程
优化代码
这种方式也存在缺点:如果每个请求过来都使用一个线程
,这时候非常浪费CPU的资源
。
所以在网络编程服务器中,是否使用单线程提高响应的效率问题,所以nio出现;
public class SocketTcpServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8080));
System.out.println(" 服务端等待接受消息");
Socket socket = serverSocket.accept();
byte[] bytes = new byte[1024];
int read = socket.getInputStream().read(bytes);
System.out.println("服务端获取到数据:"+new String(bytes));
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ClientSocket {
public static void main(String[] args) {
try {
Socket socket = new Socket();
socket.connect(new InetSocketAddress("127.0.0.1", 8080));
socket.getOutputStream().write("nice".getBytes());
} catch (Exception e) {
}
}
}
真正阻塞 是在: 读写io
public class SocketTcpServer {
public static void main(String[] args) {
final byte[] bytes = new byte[1024];
try {
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8080));
while (true){
System.out.println(" 服务端等待接受消息");
final Socket socket = serverSocket.accept();
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
@Override
public void run() {
try {
int read = socket.getInputStream().read(bytes); //io阻塞 读
System.out.println("服务端获取到数据:"+new String(bytes));
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Linux下的五种I/O模型
1)阻塞I/O(blocking I/O)
2)非阻塞I/O (nonblocking I/O)
3) I/O复用(select 和poll) (I/O multiplexing)
4)信号驱动I/O (signal driven I/O (SIGIO))
5)异步I/O (asynchronous I/O (the POSIX aio_functions))
前面四种都是同步io、第五种是异步IO;
当我们在调用一个io函数的时候,如果没有获取到数据的情况下,那么就会一直等待;等待的过程中会导致整个应用程序一直是一个阻塞的过程,无法去做其他的实现。
不管是否有获取到数据,都会立马获取结果,如果没有获取数据的话、那么就不间断的循环重试,但是我们整个应用程序不会实现阻塞。
这种非阻塞式的io还存在那些缺点?也是非常消耗cpu的资源,但是程序不会阻塞。
Cas、乐观锁与悲观锁
IO复用机制:IO实际指的就是网络的IO、多路也就是多个不同的tcp连接;复用也就是指使用同一个线程合并处理多个不同的IO操作,这样的话可以减少CPU资源。
白话文:单个线程可以同时处理多个不同的io操作,应用场景非常广泛:redis原理。Mysql连接原理
发出一个请求实现观察监听,当有数据的时候直接走我们异步回调;
白话文:小军在排队的时候 只需要去领取一个排队的号码,等到叫到了小军的时候才开始处理业务,这时候小军实际上还是可以去做其他的事情。 银行架构
异步io也就是发出请求数据之后,剩下的事情完全实现异步完成
站在多线程的角度总结:
同步整个应用代码执行顺序是从上往下执行 并且返回到结果;
异步:开启多个不同的分支实现并行执行 每个线程互不影响; 不能、
1.阻塞式io (Bio)
当我们在调用io函数的时候,如果没有获取的数据的情况下,就会一直阻塞、整个阻塞的过程中 不可以去做其他的事情。
2.非阻塞式的io
不管是否有获取到数据,都必须要返回io结果,如果没有获取数据结果的情况下,就使用循环控制不断重新获取。