Open Draymonders opened 4 years ago
https://mp.weixin.qq.com/s/rsvAmmoJiseEmjChI95m6Q
先知道原先的BIO为啥不好,才能体会到NIO的好
运行代码就可以知道,总共产生两次阻塞
ServerSocket.accept()
等待请求建立ServerSocket.getInputStream()
获取请求的输入流多线程BIO服务器虽然解决了单线程BIO无法处理并发的弱点,但是也带来一个问题:如果有大量的请求连接到我们的服务器上,但是却不发送消息,那么我们的服务器也会为这些不发送消息的请求创建一个单独的线程,那么如果连接数少还好,连接数一多就会对服务端造成极大的压力。所以如果这种不活跃的线程比较多,我们应该采取单线程的一个解决方案,但是单线程又无法处理并发,这就陷入了一种很矛盾的状态,于是就有了NIO。
方案一将建立链接
与数据读取InputStream
都进行了非阻塞的处理, 但是有问题的是, 数据非阻塞做了处理后,如果客户端不是刚建立完链接就发送数据,那么服务端是无法读取到客户端的发来的数据的
方案二对建立的每个链接都加入到了List
里面,因此可以一边判断是否有链接要建立, 另一边对所有建立的链接进行数据的读取操作
Selector
一个线程去处理一堆请求的输入与响应capcity
容量, 比如IntegerBuffer
capacity=100
代表可以存入100个int
position
当前指针位置limit
limit即可读可写的最大范围mark
缓存标记position位置
allocate
创建一个缓存区put
和 get
分别在写模式下写入和在读模式下读入flip
写模式转换为读模式clear
读模式转换为写模式rewind
position
置为0,从头开始读mark
代表记录一个临时position
, 而reset
代表还原那个临时的position
最主要的有四种, FileChannel
, SocketChannel
, ServerSocketChannel
, DatagramChannel
有四种监听事件OP_READ
, OP_WRITE
, OP_ACCEPT
, OP_CONNECT
分别是可读、可写、接收、连接
之前的是对于一个请求,新开一个线程处理。
主线程需要等待线程A,线程B执行完后才能执行. 因此可以可以使用join()
Thread a = new Thread("A");
Thread b = new Thread("B");
a.start(); b.start();
a.join(); b.join();
上述join无法获取到线程a和b是否执行成功,仅仅是等待线程a和b执行退出(可能正常退出,也可能异常退出),并且无法拿到值
Callable<Boolean> aJob = new AJob();//③
FutureTask<Boolean>aTask =
new FutureTask<>(aJob);
aJob.get();
// 同理
bJob.get();