IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> JavaNIO 学习 -> 正文阅读

[移动开发]JavaNIO 学习

Java NIO 是指 Java New IO 类库,基于多路复用IO模型实现,分为三大核心组件:Buffer、Channel、Selector,接下来以这三大组件进行测试学习。

Buffer

从管道中读取数据时,数据流向为Channel到Buffer;往管道中写入数据时,数据流向为Buffer到Channel。可以理解为Buffer是一个临时缓冲区,用于保存临时数据,Channel用于保存真实数据。以 IntBuffer 为例子进行测试:

    public static IntBuffer intBuffer;

    /**
     * 初始化 IntBuffer
     */
    public static void init() {
        intBuffer = IntBuffer.allocate(10);
        System.out.println("init done.");
    }

    /**
     * 打印 IntBuffer 参数
     */
    public static void display() {
        System.out.println("================= Java NIO Buffer Display =================");
        System.out.println("limit " + intBuffer.limit());
        System.out.println("position " + intBuffer.position());
        System.out.println("capacity " + intBuffer.capacity());
    }

    /**
     * 往 IntBuffer 写入数字
     */
    public static void write() {
        System.out.println("================= put 5 int num into intBuffer =================");
        for (int i = 0; i < 5; i++) {
            intBuffer.put(i);
        }
        System.out.println("write done.");
    }

    /**
     * 从 IntBuffer 中读取数据
     */
    public static void read() {
        System.out.println("================= read 5 int num from intBuffer =================");
        for (int i = 0; i < 5; i++) {
            System.out.println(intBuffer.get());
        }
        System.out.println("read done.");
    }

    public static void main(String[] args) {

        init();
        display();

        write();
        display();

        intBuffer.flip();
        display();

        read();
        display();

        intBuffer.clear();
        display();
    }

输出如下:

init done.
================= Java NIO Buffer Display =================
limit 10
position 0
capacity 10
================= put 5 int num into intBuffer =================
write done.
================= Java NIO Buffer Display =================
limit 10
position 5
capacity 10
================= Java NIO Buffer Display =================
limit 5
position 0
capacity 10
================= read 5 int num from intBuffer =================
0
1
2
3
4
read done.
================= Java NIO Buffer Display =================
limit 5
position 5
capacity 10
================= Java NIO Buffer Display =================
limit 10
position 0
capacity 10

Channel

以 ByteBuffer 为例子,实现简单的文件复制:

    /**
     * 文件复制测试
     * @param srcFileName
     * @param destFileName
     */
    public static void copyFile(String srcFileName, String destFileName) {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        FileChannel inputStreamChannel = null;
        FileChannel outputStreamChannel = null;
        try {
            // 获取文件输入输出流
            fileInputStream = new FileInputStream(srcFileName);
            fileOutputStream = new FileOutputStream(destFileName);

            // 获取管道
            inputStreamChannel = fileInputStream.getChannel();
            outputStreamChannel = fileOutputStream.getChannel();

            // 创建缓存区
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);

            // 从管道中读取数据到缓存区
            while (inputStreamChannel.read(byteBuffer) != -1) {
                // 缓存区从写模式转成读模式
                byteBuffer.flip();
                while (outputStreamChannel.write(byteBuffer) != 0) {

                }
                byteBuffer.clear();
            }
            // 强制刷新
            outputStreamChannel.force(true);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            close(fileInputStream);
            close(fileOutputStream);
            close(inputStreamChannel);
            close(outputStreamChannel);
        }

    }

更高效的方式应该为使用管道的 transferFrom 方法:

    public static void copyFileFast(String srcFileName, String destFileName) {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        FileChannel inputStreamChannel = null;
        FileChannel outputStreamChannel = null;
        long startTime = System.currentTimeMillis();
        try {
            // 获取文件输入输出流
            fileInputStream = new FileInputStream(srcFileName);
            fileOutputStream = new FileOutputStream(destFileName);

            // 获取管道
            inputStreamChannel = fileInputStream.getChannel();
            outputStreamChannel = fileOutputStream.getChannel();

            long size = inputStreamChannel.size();
            System.out.println("size: " + size);
            long position = 0;
            long count;
            while (position < size) {
                // 每次最多复制 1024000000 byte = 1 GB
                count = size - position > 1024000000 ? 1024000000 : size - position;
                // 复制内存,偏移量position + count长度
                position = position + outputStreamChannel.transferFrom(inputStreamChannel, position, count);
                System.out.println("position: " + position);
            }
            // 强制刷新
            outputStreamChannel.force(true);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            close(fileInputStream);
            close(fileOutputStream);
            close(inputStreamChannel);
            close(outputStreamChannel);
        }

        long endTime = System.currentTimeMillis();
        System.out.println("所需时间:" + (endTime - startTime));
    }

输出如下:

size: 4781506560
position: 1024000000
position: 2048000000
position: 3072000000
position: 4096000000
position: 4781506560
所需时间:187682

Selector

通过 Selector 可以同时监听多个 Channel ,以 SocketChannel 和?serverSocketChannel 为例子实现简单的客户端/服务器通讯:

/**
 * @Description: 基于 NIO 的 CS 测试
 * @Author: Jiansheng Ma
 * @Date: 2022/04/30/20:00
 */
public class SelectorTest {

    public static void main(String[] args) {

        try {
            // 服务端就绪
            new Server("Server1").listenAndRun();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

/**
 * 客户端,负责向服务端发送数据
 */
class Client {
    private String clientName;

    public Client(String clientName) {
        this.clientName = clientName;
    }

    public void sendData() throws IOException {
        InetSocketAddress address = new InetSocketAddress("127.0.0.1", 12345);
        SocketChannel socketChannel = SocketChannel.open(address);
        socketChannel.configureBlocking(false);
        while (!socketChannel.finishConnect()) {

        }
        // 发送数据
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        byteBuffer.put(this.clientName.concat(": ").concat(LocalDateTime.now().toString()).getBytes());
        byteBuffer.flip();
        socketChannel.write(byteBuffer);
        socketChannel.shutdownOutput();
        socketChannel.close();
    }
}

/**
 * 服务端,负责接受客户端数据并打印
 */
class Server {

    private String serverName;

    public Server(String serverName) {
        this.serverName = serverName;
    }

    public void listenAndRun() throws IOException {
        InetSocketAddress address = new InetSocketAddress(12345);
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(address);
        serverSocketChannel.configureBlocking(false);
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (selector.select() > 0) {
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            while (iterator.hasNext()) {
                SelectionKey next = iterator.next();
                if (next.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (next.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) next.channel();
                    // 读取数据
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    while (socketChannel.read(byteBuffer) > 0) {
                        byteBuffer.flip();
                        System.out.println(new String(byteBuffer.array()));
                        byteBuffer.clear();
                    }
                    socketChannel.close();
                } else {
                    System.out.println("other ops");
                }
            }
            iterator.remove();
        }
        selector.close();
    }
}


public class Test {

    public static void testSocket() {

        new Thread(() -> {
            try {
                Client clientB = new Client("ClientB");
                while (true) {
                    clientB.sendData();
                    Thread.sleep(2000);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }).start();
    }

    public static void main(String[] args) {
        testSocket();
    }
}

先开启服务端,再开启两个客户端,服务端输出如下:

ClientA: 2022-05-02T17:56:22.606                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientA: 2022-05-02T17:56:24.608                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientB: 2022-05-02T17:56:24.640                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientA: 2022-05-02T17:56:26.616                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientB: 2022-05-02T17:56:26.647                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientA: 2022-05-02T17:56:28.628                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientB: 2022-05-02T17:56:28.660                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientA: 2022-05-02T17:56:30.643                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientB: 2022-05-02T17:56:30.674                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientA: 2022-05-02T17:56:32.650                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                
ClientB: 2022-05-02T17:56:32.682                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                

关闭服务端后,客户端提示连接错误:

java.net.ConnectException: Connection refused: connect
	at sun.nio.ch.Net.connect0(Native Method)
	at sun.nio.ch.Net.connect(Net.java:454)
	at sun.nio.ch.Net.connect(Net.java:446)
	at sun.nio.ch.SocketChannelImpl.connect(SocketChannelImpl.java:648)
	at java.nio.channels.SocketChannel.open(SocketChannel.java:189)
	at Client.sendData(SelectorTest.java:41)
	at Test2.lambda$testSocket$0(Test2.java:14)
	at java.lang.Thread.run(Thread.java:745)

Process finished with exit code 0

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:29:58  更:2022-05-05 11:32:47 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 23:38:43-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码