一、简单概念介绍
1. 同步与异步
同步与异步的重点在消息通知的方式上,也就是调用结果通知的方式。
同步:同步调用请求发送后,调用者将一直等待被调用者返回消息,若无响应则一直等待无法进行后续操作,直至有消息返回。
异步:异步调用请求发送后,调用者无需等待消息返回便可进行其他操作,消息会以通知的方式告知调用者。
2.阻塞与非阻塞
阻塞:调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞:不能立刻得到结果之前,该调用不会阻塞当前线程。
二、BIO
BIO(blocking/io)即同步阻塞IO,客户端连接时服务器需开启一个线程进行处理,让我们来看下BIO的几种实现方式。
1. 单线程实现
服务端实现:
public class Server {
public static void main(String[] args) {
try {
byte[] bt = new byte[1024];
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8080));
//等待连接:阻塞状态
System.out.println("server start...");
Socket accept = serverSocket.accept();
System.out.println("connect success");
//等待返回通知:阻塞状态
int read = accept.getInputStream().read(bt);
if(read != -1){
System.out.println("result:"+new String(bt));
}
} catch (Exception e){
System.out.println(e);
}
}
}
客户端实现:
public class Clients {
public static void main(String[] args) {
try {
Socket socket = new Socket("127.0.0.1",8080);
socket.getOutputStream().write("返回结果".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
}
}
返回结果:
该种方法优势在编写逻辑简单,无线程切换带来的cpu开销与不活跃线程造成的资源浪费;劣势也很明显,在等待连接与等待消息返回时会造成系统阻塞。
2.多线程实现
服务端实现:
public class Server {
public static void main(String[] args) {
try {
byte[] bt = new byte[1024];
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(new InetSocketAddress(8080));
while (true) {
//等待连接:阻塞状态
System.out.println("server start...");
Socket accept = serverSocket.accept();
System.out.println("connect success");
new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
System.out.println("--------------------------");
int read = accept.getInputStream().read(bt);
if(read != -1){
System.out.println("result:" + new String(bt));
}
}
} catch (Exception e) {
System.out.println(e);
}
}
}).start();
}
} catch (Exception e){
System.out.println(e);
}
}
}
创建多个客户端去调用,代码与单线程客户端相同,就不重复展示,输出结果如下: