java io学习笔记

一、java io的发展历程

tips:
1、阻塞与非阻塞的概念:阻塞是当前线程在当前任务没有完成前,是不能去执行其他任务的,只能等到它的就绪条件达成后,才能继续执行当前任务。非阻塞是指一个线程不管当前任务是否已经结束,直接返回,相应的操作在后台继续处理
2、同步与异步:同步是一种可靠的有序运行的机制,当进行同步操作时,后续的任务等待当前调用的返回,才会进行下一步。异步则是其他任务不需要等待当前调用返回,通常依靠事件,回调等机制来实现任务间的执行顺序

1、bio阶段(排队打饭模式)

传统的Java io包:基于流模型实现 ,具备file抽象、输入输出的功能,交互方式是同步、阻塞的方式,在读取输入流或者写入输出流时,在读写操作完成前,线程会一直阻塞在那里,它们之间的调用是可靠的线性关系。
优点:代码简单直观,易于实现
缺点:io效率不高和扩展性存在局限性

2、nio阶段(点单等待被叫)

Java1.4中引入了nio框架:提供了bufferchannelselector等新的抽象,可以构建多路复用的、同步非阻塞io程序,同时提供更接近操作系统底层的高性能数据操作方式。
nio的主要组成部分:
buffer:高效的数据容器,除了布尔类型,所有的原始数据类型都有相应的buffer实现
channel:类似在linux操作系统上看到的文件描述符,是nio中用来支持批量式io操作的一种抽象。file和socket通常被认为是比较高级层次的抽象,而channel是更加贴近操作系统底层的抽象,这也使得nio得以充分利用现代操作系统的底层机制,获得特定场景的优化,例如dma(direct memory access),不同层次之间的抽象是相互关联的,我们可以通过socket获取channel反之亦然
selector:nio实现多路复用的基础,提供了一种高效的机制,可以检测到注册在selector上的多个channel中是否有channel处于就绪状态 ,进而实现了单线程对多个channel的高效管理,selector同样是基于底层操作系统机制,不同模式不同版本都存在区别,linux上依赖epoll,windows上nio2依赖于iocp
charset:根据unicode字符串定义,nio也提供了相应的解码器等

nio多路复用小栗子:

public class NIOServer extends Thread {
    public void run() {
        try (Selector selector = Selector.open();
            ServerSocketChannel serverSocket = ServerSocketChannel.open();) {// 创建Selector和Channel
            serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));
            serverSocket.configureBlocking(false);
            // 注册到Selector,并说明关注点
            serverSocket.register(selector, SelectionKey.OP_ACCEPT);
            while (true) {
                selector.select();// 阻塞等待就绪的Channel,这是关键点之一
                Set<SelectionKey> selectedKeys = selector.selectedKeys();
                Iterator<SelectionKey> iter = selectedKeys.iterator();
                while (iter.hasNext()) {
                    SelectionKey key = iter.next();
                   // 生产系统中一般会额外进行就绪状态检查
                    sayHelloWorld((ServerSocketChannel) key.channel());
                    iter.remove();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    private void sayHelloWorld(ServerSocketChannel server) throws IOException {
        try (SocketChannel client = server.accept();) {          client.write(Charset.defaultCharset().encode("Hello world!"));
        }
    }

	 public static void main(String[] args) throws IOException {       
	    DemoServer server = new DemoServer();       
	    server.start();       
	    try (Socket client = new Socket(InetAddress.getLocalHost(), server.getPort())) {            	             	
	          BufferedReader bufferedReader = new BufferedReader(new                   
	          InputStreamReader(client.getInputStream()));          
	          bufferedReader.lines().forEach(s -> System.out.println(s));       
	     }   
	 }
}

主要步骤:
1、通过Selector.open()创建一个Selector,类似调度员的角色
2、然后创建一个ServerSocketChannel,并且向Selector注册,通过指定SelectionKey.OP_ACCEPT,告诉调度员,它关注的是新的请求(我们必须明确配置非阻塞模式,阻塞模式下是不允许注册操作的,会抛出IllegalBlockingModeException异常)
3、Selector阻塞在select操作,当有Channel发生接入请求,就会被唤醒
4、在sayHelloWorld中,通过SocketChannel和buffer进行数据操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值