阻塞:做某件事情,直到完成,除非超时,如果没有完成,继续等待
非阻塞:做一件事情,尝试着做,如果说不能做完,就不做了,意思就是直接返回,如果能够做完,就做
传统IO Socket编程
package io;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static java.util.concurrent.Executors.*;
/**
* @author chengshengwen
* @date 2019-05-27
*
*/
public class TraditionalSocketDemo {
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
ExecutorService threadPool = newCachedThreadPool();
ServerSocket serverSocket = new ServerSocket(7777);
System.out.println("服务端启动。。。");
while(true){
//获取 socket客户端套接字,这里有一个阻塞
final Socket accept = serverSocket.accept();
//
threadPool.execute(new Runnable() {
public void run() {
try{
System.out.println("有新客户端连接上来了。。。");
InputStream inputStream = accept.getInputStream();
byte[] b = new byte[1024];
while(true){
//这里也是一个阻塞点
int data = inputStream.read();
if(data != -1){
String s = new String(b, 0, data);
System.out.println(s);
}else{
break;
}
}
}catch (Exception e){
}
}
});
}
}
}
优点:效率快
缺点:占用大量的系统资源,成本大。
系统资源,IO,存储,内存,CPU
NIO(角色是一个线程)
1、增加了一个重要角色(Selector),主要负责调度和监控客户端和服务端(调度器)
2、由阻塞方式改成了非阻塞(non-blocking),
package io;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
/**
* @author chengshengwen
* @date 2019-05-27
*
*/
public class NioSocketDemo {
private Selector selector;//通道选择器(管理器)
public static void main(String[] args) throws IOException {
NioSocketDemo nioSocketDemo = new NioSocketDemo();
nioSocketDemo.initServer(8888);
nioSocketDemo.listenSelector();
}
public void initServer(int port) throws IOException{
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);//非阻塞
serverSocketChannel.socket().bind(new InetSocketAddress(port));
this.selector = Selector.open();
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
/**/
System.out.println("服务已启动。。。");
}
public void listenSelector() throws IOException {
//轮询监听selector
while (true){
//等待客户连接
//select 模型,多路复用,这是一个阻塞点
this.selector.select();
Iterator<SelectionKey> iterator = this.selector.selectedKeys().iterator();
while (iterator.hasNext()){
SelectionKey next = iterator.next();
iterator.remove();
//处理请求
handler(next);
}
}
}
/**
* 处理客户端请求
* @param key
*/
private void handler(SelectionKey key)throws IOException{
System.out.println("有客户端连接上来了。。。");
if(key.isAcceptable()){
//处理客户端连接请求事件
ServerSocketChannel socketChannel = (ServerSocketChannel)key.channel();
SocketChannel accept = socketChannel.accept();
//接收客户端发送的信息时,需要给通道设置读的权限
socketChannel.register(selector,SelectionKey.OP_READ);
}else if(key.isReadable()){
//处理读的事件
SocketChannel socketChannel = (SocketChannel)key.channel();
ByteBuffer allocate = ByteBuffer.allocate(1024);
int read = socketChannel.read(allocate);
if(read > 0){
String s = new String(allocate.array(),"GBK").trim();
System.out.println("服务端收到数据," + s);
}else{
System.out.println("客户端关闭了。。。");
key.channel();
}
}
}
}
总结:
IO与NIO的区别:
IO:如果有100个客户端,那所要的服务端就需要100个服务端(线程)
NIO:如果有100个客户端,那所需要的只有10个服务端(线程)
真正关心的阻塞点:读取数据