大数据笔记

NIO

IO流,作用:用于传输数据

IO分类

同步:一个对象或者一段逻辑在一段时间内只能被一个线程来用
异步:一个对象或者一段逻辑在一段时间内可以允许多个线程来用
阻塞:在程序没有在获取结果之前,这个线程不会继续往下执行也不会报错:列如socket的IO流读写
非阻塞:在程序没有在获取结果的时候,不会等待而是继续执行或者报错

1.JDK1.0 BIO:(blockingIO)同步阻塞:单向传输

一对一连接: 客户端发起一个请求服务端就会产生一个线程去处理,如果大量的请求,会产生大量的线程,会造成卡顿等一些现象,
无用连接: 建立连接后不发送任何操作,服务器线程就会被大量占用无法释放,资源浪费
阻塞: 一旦阻塞,程序的执行就会延长,执行效率降低

2.JDK1.4 NIO:(NonBlockingIO)同步非阻塞 :通信机制上等运用

NIO三大组件:

Buffer(缓存区)是一个抽象类所以不能直接new

作用::存储数据,底层结构依靠数组来存储数据,并且只能针对基本类型(8种)进行存储数据。针对基本类型(8种)提供了7个实现类ByteBuffer(实际使用的更多),LongBuffer,ShortBuffer,IntBuffer,FloatBuffer,DubbleBuffer,CharBuffer。没有布尔类型的实现类,用其他的来代替,0或者1来表示true或者false,利用ByteBuffer来实现传输。
(1)创建缓存区:ByteBuffer buffer = ByteBuffer.allocate(1024),先构建才能put填充数据,适用于未知的数据
添加数据buffer.put(“abs‘.getBytes())
获取数据buffer.get()
获取长度(容量位:标记缓存区的容量,容量定义好,不能改变)buffer.capacity() = 1024
获取操作位 buffer.position()
获取元素(通过position操作位,类似于数组下表,从缓存区的零开始,操作一位后移一位,无论是put还是get都会移动) buffer.position()
限制位limit,初始时和capactiy重合,允许用满
获取缓存区的数据byte[] array = buffer.array() new String(array,0, buffer.position())
buffer.flip() new String(array,0,buffer.limit())
反转缓存区遍历数据:buffer.flip()等价于下边俩个步骤
1.现将limit移动到position的位置 buffer.limit(buffer.position())
2.将position移动到最初的位置buffer.position(0)
while(buffer.position()<buffer.limit()等价于buffer.hasRemaining()){
byte a = buffer.get();每get一次向后移动一位
打印a}
ByteBuffer提供了allocate方法底层是依靠字节数组,参数表示的是字节数组的容量
(2)创建缓存区:ByteBuffer buffer = ByteBuffer.wrap(“sjgfjkgh”.getbyte()),适用于已知的数据,position默认指向第0位,只要没有进行get或者put操作就不会进行移动

Channel(通道:作用传输数据)

(1).面向buffer操作,在传输的时候,以ByteBuffer位单位进行传输 (2).不同于BIO,可以实现双向传输
常见的Channel:
a:文件 FileChannel()
b: UDP DatagramChannel
c: TCP 考虑稳定性用TCP较多

1.SocketChannel(表示客户端)

(1)开启客户端通道
SocketChannel sc = SocketChannel.open()
可以设置为非阻塞如果不设置为阻塞
sc.configureBlocking(false),无论连接与否都不会等待,而是继续往下执行
(2)建立连接 (阻塞):sc.connect(New InetSocketAddress(“localhost”,8080))阻塞3秒,不指定,默认为阻塞
int i= 0;
判断连接是否建立while(!sc.connected()){
/如果没有建立,试图再次建立连接/sc.finishConnect()
/如果多次试图建立连接,既无法连接finishConnect底层会根据网络条件自动计数,会自动抛出异常/ }
(3)构建字节缓存区ByteBuffer buffer = ByteBuffer.wrap(“sjgfjkgh”.getbyte()),
(4)往外写出数据 sc.write(buffer)
(5)关流 sc.close()

2.ServerSocketChannel(表示服务器端)

(1)开启服务器端的通道
ServerSocketChannel ssc = ServerSocketChannel.open()
(2)绑定监听端口
ssc.bind(new InetSocketAddress(8080))
设置为非阻塞 sc.configureBlocking(false)
判断连接是否建立while(!sc.==null){
/如果没有建立,试图再次建立连接/sc.accetp()
/如果多次试图建立连接,既无法连接finishConnect底层会根据网络条件自动计数,会自动抛出异常/ }
(3)接收连接
SocketChannel sc = ssc.accept()(默认为阻塞)无论连接与否都不会等待,而是继续往下执行
(4)准备字节缓存区(接收未知的数据) ByteBuffer buffer = ByteBuffer.allocate(1024),
(5)读取数据 sc.read(buffer);
(6)解析数据 byte[] array = buffer.array() ; System.out.println(new String(array,0, buffer.position()))
(7) 关流 sc.close()

Selector(多路复用选择器)

作用:针对Channel事件来进行选择
要求注册的通道必须是非阻塞的
事件指的是;客户端和服务器端可能产生的操作,(可以设置在任意的俩端) Selector 一般设计在服务器端
在这里插入图片描述
创建服务器端,并将Selector 设置在服务器端

1)开启服务器端的通道
(2)绑定监听端口
   设置为非阻塞  ssc.configureBlocking(false)
  (3)  开启Selector  Selector  selt = Selector .open();
  (4) 将ssc绑定到Selector上绑定需要让Selector过滤的事件
  ssc.register(selc,SelectionKey.OP_ACCEPT)表示区接收连接
  实际开发中,服务器开启之后应该是不关闭的
  如果服务器长时间开启,会产生大量的连接,可能有用可能没用
 模拟开启while(true){
   
  筛选没用的连接 selt.select(); 筛选完成后,剩余的连接都能够发出服务器端的对应的操作,即有用连接,可能会触发服务器的操作
  确定触发了什么操作accept/read/write
  Set<SelectionKey> set = selt.SelectedKeys()
  Iterator <SelectionKey> it = set.Iterator()
  while(it.hasNext()){
   
  SelectionKey key = it.next()
  //可接收事件
  if(key.isAcceptable()){
   
  //先将事件中对应的通道拿出来
  ServerSocketChannel ssc = (ServerSocketChannel)key.channel();
  //接收连接
  SocketChannel sc = ssc.accept();
   //设置为非阻塞
   //如果是可读事件,注册可读事件,如果写出则注册可写事件,最后一次register会覆盖前一次的register
  sc.register(selc
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值