java nio之selector

简介:   一、selector简介:选择器提供选择执行已经就绪的任务的能力.从底层来看,Selector提供了询问通道是否已经准备好执行每个I/O操作的能力。Selector 允许一个单一的线程来操作多个 Channel。

  一、selector简介:选择器提供选择执行已经就绪的任务的能力.从底层来看,Selector提供了询问通道是否已经准备好执行每个I/O操作的能力。Selector 允许一个单一的线程来操作多个 Channel。仅用单个线程来处理多个Channels的好处是,只需要更少的线程来处理通道。事实上,可以只用一个线程处理所有的通道,这样会大量的减少线程之间上下文切换的开销。

  二、选择器的创建以及使用

  1)创建 

Selector selector = Selector.open();

  2)注册选择器(Channel这里不介绍)

socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ)

  注意:一个通道注册到选择器中,必须是非阻塞的。

  3)注册模式有4种

SelectionKey.OP_CONNECT 
SelectionKey.OP_ACCEPT 
SelectionKey.OP_READ 
SelectionKey.OP_WRITE

  4)SelectionKey的使用

  在选择其中会存在多个选择键SelectionKey,每一个选择键的类型可能不一样,所以我们这里需要判定是哪一种类型

selector.selectedKeys() //获取所有选择键
selectionKey.isConnectable() //是否是连接选择键
selectionKey.isReadable() //读取
selectionKey.isWritable() //写入
selectionKey.isAcceptable() //接收

  获取对应的选择键过后可以强转成对应的通信管道。(示例)

SocketChannel channel = (SocketChannel) selectionKey.channel();

  三、聊天室的基本写法(基本使用都在里面)

  1)客户端

package com.troy.nio.application;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class Client {

    //选择器
    private static Selector selector;
    //通信管道
    private static SocketChannel socketChannel;
    public static void main(String[] args) {
        try {
            clientInit();
            listen();
            //发送数据
            while (true) {
                Thread.sleep(1000);
                socketChannel.write(ByteBuffer.wrap(("hello server!").getBytes()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //初始化选择器和发送数据
    private static void clientInit() throws Exception {
        //打开一个通道管理器
        selector = Selector.open();
        //获取一个通信管道
        socketChannel = SocketChannel.open();
        //设置对应的发送地址和端口
        socketChannel.connect(new InetSocketAddress("localhost",9000));
        //设置非阻塞
        socketChannel.configureBlocking(false);
        //注册一个写入事件
        socketChannel.register(selector, SelectionKey.OP_READ);
    }

    //监听服务器返回的数据
    private static void listen() throws Exception {
        Runnable runnable = () -> {
            while (true) {
                try {
                    //这里会一直阻塞,直到事件过来
                    selector.select();
                    //在选择器中获取对应的注册事件
                    Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                    while (iterator.hasNext()) {
                        //注册事件
                        SelectionKey selectionKey = iterator.next();
                        iterator.remove();
                        //判断是否是读事件
                        if (selectionKey.isReadable()) {
                            //获取对应通信管道,并处理层数据
                            SocketChannel channel = (SocketChannel) selectionKey.channel();
                            //一次性读取数据量,这里应该做循环,我这里方便没有做
                            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                            channel.read(byteBuffer);
                            byteBuffer.flip();
                            System.out.println(new String(byteBuffer.array()).trim());
                        }
                    }
                } catch (Exception e) {
                    throw new RuntimeException(e.getMessage());
                }
            }
        };
        new Thread(runnable).start();
    }
}

  2)服务端

package com.troy.nio.application;


import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class Server {

    //选择器
    private static Selector selector;
    //服务端通信管道
    private static ServerSocketChannel channel;
    public static void main(String[] args) {
        try {
            serverInit();
            listen();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //初始化
    private static void serverInit() throws IOException {
        //打开一个选择器
        selector = Selector.open();
        //打开一个服务端通信管道
        channel = ServerSocketChannel.open();
        //设置接收端口
        channel.socket().bind(new InetSocketAddress(9000));
        //设置非阻塞
        channel.configureBlocking(false);
        //注册接收事件
        channel.register(selector, SelectionKey.OP_ACCEPT);
    }

    //监听
    private static void listen() throws IOException {
        while (true) {
            //形成阻塞事件,接口完成后进行下一步
            selector.select();
            //获取选择器中的事件
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey selectionKey = iterator.next();
                iterator.remove();
                //判断是否是接受事件
                if (selectionKey.isAcceptable()) {
                    SocketChannel socketChannel = channel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector,SelectionKey.OP_READ);
                }
                //是否是可读事件
                if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    //这里的目的是当这个服务端一直存在,因为读取数据存在异常,直接处理掉,下一个客户端景来可以继续接受
                    try {
                        socketChannel.read(byteBuffer);
                    } catch (Exception e) {
              selectionKey.cancel();
continue; } byteBuffer.flip(); System.out.println(new String(byteBuffer.array()).trim()); socketChannel.write(ByteBuffer.wrap("hello client!".getBytes())); } } } } }

 

相关文章
|
6天前
|
监控 Java API
探索Java NIO:究竟在哪些领域能大显身手?揭秘原理、应用场景与官方示例代码
Java NIO(New IO)自Java SE 1.4引入,提供比传统IO更高效、灵活的操作,支持非阻塞IO和选择器特性,适用于高并发、高吞吐量场景。NIO的核心概念包括通道(Channel)、缓冲区(Buffer)和选择器(Selector),能实现多路复用和异步操作。其应用场景涵盖网络通信、文件操作、进程间通信及数据库操作等。NIO的优势在于提高并发性和性能,简化编程;但学习成本较高,且与传统IO存在不兼容性。尽管如此,NIO在构建高性能框架如Netty、Mina和Jetty中仍广泛应用。
21 3
|
13天前
|
存储 监控 Java
Java的NIO体系
通过本文的介绍,希望您能够深入理解Java NIO体系的核心组件、工作原理及其在高性能应用中的实际应用,并能够在实际开发中灵活运用这些知识,构建高效的Java应用程序。
30 5
|
5月前
|
Java 大数据
解析Java中的NIO与传统IO的区别与应用
解析Java中的NIO与传统IO的区别与应用
|
1月前
|
消息中间件 缓存 Java
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
零拷贝技术 Zero-Copy 是指计算机执行操作时,可以直接从源(如文件或网络套接字)将数据传输到目标缓冲区, 而不需要 CPU 先将数据从某处内存复制到另一个特定区域,从而减少上下文切换以及 CPU 的拷贝时间。
java nio,netty,kafka 中经常提到“零拷贝”到底是什么?
|
2月前
|
Java
让星星⭐月亮告诉你,Java NIO之Buffer详解 属性capacity/position/limit/mark 方法put(X)/get()/flip()/compact()/clear()
这段代码演示了Java NIO中`ByteBuffer`的基本操作,包括分配、写入、翻转、读取、压缩和清空缓冲区。通过示例展示了`position`、`limit`和`mark`属性的变化过程,帮助理解缓冲区的工作原理。
38 2
|
3月前
|
存储 网络协议 Java
Java NIO 开发
本文介绍了Java NIO(New IO)及其主要组件,包括Channel、Buffer和Selector,并对比了NIO与传统IO的优势。文章详细讲解了FileChannel、SocketChannel、ServerSocketChannel、DatagramChannel及Pipe.SinkChannel和Pipe.SourceChannel等Channel实现类,并提供了示例代码。通过这些示例,读者可以了解如何使用不同类型的通道进行数据读写操作。
Java NIO 开发
|
4月前
|
Java
"揭秘Java IO三大模式:BIO、NIO、AIO背后的秘密!为何AIO成为高并发时代的宠儿,你的选择对了吗?"
【8月更文挑战第19天】在Java的IO编程中,BIO、NIO与AIO代表了三种不同的IO处理机制。BIO采用同步阻塞模型,每个连接需单独线程处理,适用于连接少且稳定的场景。NIO引入了非阻塞性质,利用Channel、Buffer与Selector实现多路复用,提升了效率与吞吐量。AIO则是真正的异步IO,在JDK 7中引入,通过回调或Future机制在IO操作完成后通知应用,适合高并发场景。选择合适的模型对构建高效网络应用至关重要。
101 2
|
4月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
157 0
|
5月前
|
安全 Java Linux
(七)Java网络编程-IO模型篇之从BIO、NIO、AIO到内核select、epoll剖析!
IO(Input/Output)方面的基本知识,相信大家都不陌生,毕竟这也是在学习编程基础时就已经接触过的内容,但最初的IO教学大多数是停留在最基本的BIO,而并未对于NIO、AIO、多路复用等的高级内容进行详细讲述,但这些却是大部分高性能技术的底层核心,因此本文则准备围绕着IO知识进行展开。
192 1
|
4月前
|
存储 网络协议 Java
【Netty 神奇之旅】Java NIO 基础全解析:从零开始玩转高效网络编程!
【8月更文挑战第24天】本文介绍了Java NIO,一种非阻塞I/O模型,极大提升了Java应用程序在网络通信中的性能。核心组件包括Buffer、Channel、Selector和SocketChannel。通过示例代码展示了如何使用Java NIO进行服务器与客户端通信。此外,还介绍了基于Java NIO的高性能网络框架Netty,以及如何用Netty构建TCP服务器和客户端。熟悉这些技术和概念对于开发高并发网络应用至关重要。
94 0