命令模式和责任链模式。
----------------------------------------1-1-----------------------------------------------
-----------------------------------1-2-----------------------------------------------------
---------------------------------------------1-3-----------------------------------------------------
-----------------------------------------------------1-4---------------------------------------------------------
BIO:一个线程一个连接,没有缓冲区。
NIO:多个channel注册同一个selector,有缓冲区。
-----------------------------------1-5-----------------------------------------------------
public static void main(String[] args) throws Exception {
//线程池机制
//思路
//1. 创建一个线程池
//2. 如果有客户端连接,就创建一个线程,与之通讯(单独写一个方法)
ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
//创建ServerSocket
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服务器启动了");
while (true) {
System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
//监听,等待客户端连接
System.out.println("等待连接....");
final Socket socket = serverSocket.accept();
System.out.println("连接到一个客户端");
// 这块是阻塞的要是有连接来了就创建线程去读取数据
//就创建一个线程,与之通讯(单独写一个方法)
newCachedThreadPool.execute(new Runnable() {
public void run() { //我们重写
//可以和客户端通讯
handler(socket);
}
});
}
}
//编写一个handler方法,和客户端通讯
public static void handler(Socket socket) {
try {
System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
byte[] bytes = new byte[1024];
//通过socket 获取输入流
InputStream inputStream = socket.getInputStream();
//循环的读取客户端发送的数据
while (true) {
System.out.println("线程信息 id =" + Thread.currentThread().getId() + " 名字=" + Thread.currentThread().getName());
System.out.println("read....");
int read = inputStream.read(bytes);
if(read != -1) {
System.out.println(new String(bytes, 0, read
)); //输出客户端发送的数据
} else {
break;
}
}
}catch (Exception e) {
e.printStackTrace();
}finally {
System.out.println("关闭和client的连接");
try {
socket.close();
}catch (Exception e) {
e.printStackTrace();
}
}
}
简单的BIO模型。
重点:阻塞的两个方法就是read和accept,经典啊。两个while都是阻塞的。主线程去监听,不断的切换子线程去新建连接。
socket.accept。
inputstream.read。
-----------------------------------1-6-----------------------------------------------------
总结。
问题分析:
--------------------------------------------------1-7---------------------------------------------------------------
NIO的主要组件:通道,缓冲区和selector。
主要是一个selector是一个线程,多个通道也就是socket可以注册到一个selector上面。
找个就是NIO的好处。
每一个通道对应一个buffer。
NIO是同步非阻塞的。
select可以注册很多通道,每个通道对应一个请求。
通道没有任务我这个线程还可以执行其他的任务。
-----------------------------------1-8-----------------------------------------------------
代码:
NIO的Buffer是有很多的种类的。
package com.atguigu.nio;
import java.nio.IntBuffer;
public class BasicBuffer {
public static void main(String[] args) {
//举例说明Buffer 的使用 (简单说明)
//创建一个Buffer, 大小为 5, 即可以存放5个int
IntBuffer intBuffer = IntBuffer.allocate(5);
//向buffer 存放数据
// intBuffer.put(10);
// intBuffer.put(11);
// intBuffer.put(12);
// intBuffer.put(13);
// intBuffer.put(14);
for(int i = 0; i < intBuffer.capacity(); i++) {
intBuffer.put( i * 2);
}
//如何从buffer读取数据
//将buffer转换,读写切换(!!!)
/*
public final Buffer flip() {
limit = position; //读数据不能超过5
position = 0;
mark = -1;
return this;
}
*/
intBuffer.flip(); // 方法很主要 buffer的读写切换的
intBuffer.position(1);//1,2
System.out.println(intBuffer.get());
intBuffer.limit(3);
while (intBuffer.hasRemaining()) {
System.out.println(intBuffer.get());
}
}
}
System.out.println(intBuffer.get());
// get是只读取下一位
BIO是流处理数据,NIO是块处理数据。
如何为非阻塞的,数据缓冲区到一定的量才会去读取。
--------------------------------------------------------------1-9--------------------------------------------------------------
0
重点:
1.每个channel都有一个buffer
2.一个selector对应一个线程。一个线程对应对应多个channel。
selector会根据不同的事件就是关心的读取?写入?还是连接?在各个通道上切换。
Buffer可以双向,channel也可以双向。
-----------------------------------1-10-----------------------------------------------------