Java NIO

1. IO分类概述

1.1 阻塞与非阻塞

        阻塞(Blocking)和非阻塞(Nonblocking)是在计算机编程中用于描述I/O操作的两个重要概念。阻塞与非阻塞描述的是线程在访问某个资源时,在该资源没有准备就绪期间的处理方式。

        1、阻塞:阻塞是指在进行I/O操作时,当前线程会被挂起,等待数据的就绪或操作的完成。

  • 在阻塞状态下,线程会一直等待,直到条件满足或超时才会继续执行
  • 阻塞式I/O操作会导致调用线程无法执行其他任务,直到I/O操作完
  • 例如,在读取文件时,如果没有数据可用,线程会一直等待直到有数据可读

        2、非阻塞:非阻塞是指进行I/O操作时,当前线程不会被挂起,而是立即返回并继续执行其他任务。

  • 在非阻塞状态下,即使I/O操作无法立即完成,线程也可以继续执行其他操作,而不需要一直等待
  • 非阻塞式I/O操作通常会返回一个状态或错误码,指示操作是否完成或需要进一步处理
  • 应用程序可以通过不断轮询状态来判断是否可以进行下一步操作

1.2 同步与异步

        同步(synchronous)与异步(asynchronous)描述的是线程在发出请求后,是否等待结果。

        1、同步(Synchronous):同步是指程序按照顺序执行,并等待某个操作完成后再继续执行下一个操作。

  • 在同步操作中,程序主动发起请求并等待结果返回,直到结果返回后才能继续执行后续操作
  • 同步操作通常是阻塞的,即在等待结果时当前线程会被挂起,无法执行其他任务
  • 典型的同步操作包括函数调用、阻塞式I/O操作等

        2、异步(Asynchronous):异步是指程序在发起某个操作后,不需要立即等待操作完成,而是继续执行后续的操作。

  • 在异步操作中,程序不会阻塞等待结果的返回,而是通过回调、轮询或事件通知等机制来获取结果或处理完成的事件
  • 异步操作允许程序并发执行多个任务,提高了系统的并发性和响应性。典型的异步操作包括异步函数调用、非阻塞式I/O操作、异步任务等

1.3 IO的分类

        当涉及I/O操作时,可以根据是否阻塞和是否异步的角度将其分为以下四类:

        1、阻塞式I/O(Blocking I/O)

  • 特点:在进行I/O操作时,当前线程会被阻塞,直到数据就绪或操作完成
  • 工作原理:当进行I/O操作时,线程会等待直到数据准备好或操作完成,在等待期间,线程无法执行其他任务

        2、非阻塞式I/O(Non-Blocking I/O)

  • 特点:进行I/O操作时,当前线程不会被阻塞,立即返回并继续执行其他任务
  • 工作原理:当进行I/O操作时,如果数据尚未准备好或操作无法立即完成,操作会立即返回一个状态指示暂时不可用

        3、I/O多路复用(I/O Multiplexing)

  • 特点:允许一个线程同时监视多个I/O通道的就绪状态,提高了系统的并发性能
  • 工作原理:通过操作系统提供的I/O复用机制,将多个I/O通道注册到一个选择器上,然后使用选择器进行轮询以确定哪些通道就绪

        4、异步I/O(Asynchronous I/O)

  • 特点:在进行I/O操作时,不需要立即等待操作完成,可以继续执行其他任务,通过回调或事件机制来处理操作结果
  • 工作原理:应用程序提交I/O请求后立即返回,并使用回调、轮询或事件通知等方式来处理操作完成的通知

        这四种I/O模型各有优劣,并适用于不同的应用场景:

  • 阻塞式I/O适用于简单的同步操作
  • 非阻塞式I/O适用于需要处理多个连接的场景
  • I/O多路复用适用于需要监视多个连接的场景
  • 异步I/O适用于需要高性能和扩展性的场景

        根据具体的应用需求和系统特点,可以选择合适的I/O模型来实现高效的数据传输和处理。

2. Java NIO

2.1 Java NIO概述

        在Java编程中,经常听到BIO,NIO,AIO等名词,这些名词一般指的是Java语言为实现不同类型的I/O操作所提供的API。

        1、Java IO:Java IO是JDK 1.0版本其自带的用于读取和写入数据的API。因其同步、阻塞的特征,被归类为同步阻塞式IO(Blocking IO),即Java BIO。

        2、Java NIO(New IO):是JDK 1.4开始提供的同步非阻塞式的IO操作API。因其同步、非阻塞的特征,开发者一般将Java NIO理解为Java Non-Blocking IO。

        3、Java NIO 2.0:是JDK 1.7开始提供的异步非阻塞式的IO操作API,因其是在NIO的基础上进行了改进,称为NIO 2.0。因其异步、非阻塞的特征,开发者一般将Java NIO 2.0称为Java AIO。

        下面以一个Web服务器的例子介绍Java BIO和Java NIO在实际使用中的差别。

        基于BIO的场景:

        基于NIO的场景:

2.2 Java BIO模型

        Java BIO和NIO采用了2种不同的模型。BIO使用了面向流(Stream Oriented)的模型。流(Stream)可以理解为从源节点到目标节点的数据通道,传输的数据像水流一样从源节点流向目标节点。

        面向流的特点:

  • 单向的:一个流中的数据仅能从一个方向流向另一个方向
  • 面向字节的:程序每次可以从流中读取1到多个字节,或写入1到多个字节
  • 无缓冲的:从流中读取数据后,流中的数据消失
  • 顺序访问:仅能按顺序逐个访问流中的数据,不能在流中的数据中前后移动

2.3 Java NIO模型

        Java NIO使用了面向缓冲区(Buffer Oriented)的,基于通道(Channel Based)的模型。模型的不同使得BIO和NIO在功能上和操作上有着不同的特点。

        在面向缓冲的模型中,数据通过数据通道(Channel)被读入/写入到一个缓冲区(Buffer)中,然后从中进行处理。

        可以使用一个生活中的例子来理解:现在需要从房间A搬运一些纸质文件到房间B,房间A和房间B之间通过一个走廊相连。搬运文件时,先将文件放到一个文件箱中,再搬着文件箱从A房间移动到B房间。

        在这个例子中,房间A和房间B分别是数据传输的起点和终点。起点和终点之间的走廊是Channel,临时存放纸质文件的文件箱是Buffer。

        面向缓冲的特点:

  • 双向的:通道可以用于读或写,也可以同时用于读写
  • 面向字节块:程序每次可以从缓冲区中获取一组字节数据
  • 缓冲的:缓冲中的数据可以被多次访问
  • 任意访问:允许在缓冲中的数据中前后移动

2.4 两种模型的对比

        Java BIO下的执行流程:

        Java NIO下的执行流程:

3. Java NIO API

3.1 Buffer

        Buffer(缓冲区)是Java NIO中提供的用于存储数据的容器。Buffer底层依靠数组来存储数据,并提供了对数据的结构化访问以及维护读写位置等信息的功能。

        Buffer只能用于存储基本类型的数据。在NIO中,针对八种基本类型提供了7个实现类。考虑到实际过程中,数据是以字节的形式来存储和传输,所以更多的使用的是ByteBuffer。

        Buffer是一个抽象类:

        其中定义了4个关于底层数组信息的核心属性:

  • capacity:容量位,用于标记该缓冲区的容量,缓冲区创建好之后不可变
  • position:操作位,用于指向要操作的位置,实际意义类似于数组中的下标,在缓冲区刚创建的时候指向0
  • limit:限制位,用于限制操作位position所能达到的最大位置。在缓冲区刚创建的时候指向容量位
  • mark:标记位,用于进行标记,在缓冲区刚创建的时候指向-1,默认不启用

        Buffer初始时的状态:

        示例代码:

        输出结果:

        Buffer写入部分数据后的状态:

        示例代码:

        输出结果:

        Buffer反转后的状态:

        示例代码:

        输出结果:

import java.nio.ByteBuffer;

public class BufferDemo {
    public static void main(String[] args) {
        //创建Buffer
        ByteBuffer buf = ByteBuffer.allocate(10);
        printBufferState(buf);
        // 写入数据到ByteBuffer
        String message = "Hello NIO";
        buf.put(message.getBytes());
        System.out.println("Before flip():");
        printBufferState(buf);
        // 反转缓冲区
        buf.flip();
        // 打印切换到读模式后的状态
        System.out.println("After flip():");
        printBufferState(buf);

        // 读取数据
        byte[] data = new byte[buf.limit()];
        buf.get(data);
        // 打印读取到的数据
        System.out.println("Read data: " + new String(data));
    }
    public static void printBufferState(ByteBuffer buf){
        //输出3个变量的值
        System.out.println("position="+buf.position()+",limit="+buf.limit()+",capacity="+buf.capacity());
    }
}

3.2 Channel

        Channel(通道)是Java NIO中提供的用于传输数据的工具,代表了源节点和目标节点之间的数据通道。Channel与Stream相似,但是略有不同:

  • Channel是双向的
  • Channel默认是阻塞的,可以设置为非阻塞
  • Channel是面向缓冲区操作的

        Java NIO中常用的Channel实现类如下:

        其中:

  • FileChannel:从文件读取数据和向文件读取数据
  • DatagramChannel:可以通过UDP协议在网络上读写数据
  • SocketChannel:可以通过TCP协议在网络上读写数据
  • ServerSocketChannel:允许您侦听传入的 TCP 连接,就像 Web 服务器一样。 对于每个传入连接,都会创建一个 SocketChannel
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class FileChannelDemo {
    public static void main(String[] args) throws Exception {
        readDemo();
        writeDemo();
    }
    public static void readDemo() throws Exception {
        RandomAccessFile aFile = new RandomAccessFile("data/hello.txt", "rw");
        FileChannel inChannel = aFile.getChannel();
        ByteBuffer buf = ByteBuffer.allocate(10);
        int bytesRead = inChannel.read(buf);
        while (bytesRead != -1) {
            System.out.println("\n====>Read " + bytesRead);
            buf.flip();
            while(buf.hasRemaining()){
                System.out.print((char) buf.get()+" ");
            }
            buf.clear();
            bytesRead = inChannel.read(buf);
        }
        aFile.close();
    }

    public static void writeDemo() throws Exception {
        RandomAccessFile aFile = new RandomAccessFile("data/hello2.txt", "rw");
        FileChannel channel = aFile.getChannel();
        ByteBuffer buf = ByteBuffer.wrap("Hello Channel!".getBytes());
        int len=channel.write(buf);
        System.out.println("len="+len);
        aFile.close();
    }
} 

3.3 Selector

        Selector 是 Java NIO 提供的一个组件,它可以检查一个或多个Channel 实例,并确定哪些通道准备好用于读、写等操作。 通过这种方式,单个线程可以管理多个通道,从而管理多个网络连接。

        Selector是基于事件驱动的,供提供了4类事件:connect、accept、read和write。

        这四类事件定义在SelectionKey中:

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

        想要使用Selector来管理Channel,需要先向Selector注册该Channel实例,可以通过SelectableChannel.register()方法实现。

// 将channel设置为非阻塞模式
channel.configureBlocking(false);
// 将通道注册到选择器,并指定关注事件为读事件
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);

        需要注意,Channel 必须处于非阻塞模式才能与 Selector 一起使用。 也就是说,不能将 FileChannel 与 Selector 一起使用,因为 FileChannel 无法切换到非阻塞模式。SocketChannel是可以与Selector搭配使用的。

        创建一个ServerSocketChannel监听8080端口,并使用Selector来处理客户端的连接和数据读取。同时,创建了多个客户端线程,模拟并发访问。每个客户端线程会连接到服务器,并发送数据,然后接收服务器的响应。

        Server端程序代码:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

public class Server {
    public static void main(String[] args) throws IOException {
        // 创建Selector
        Selector selector = Selector.open();

        // 创建ServerSocketChannel并绑定端口
        ServerSocketChannel serverChannel = ServerSocketChannel.open();
        serverChannel.bind(new InetSocketAddress(8080));
        serverChannel.configureBlocking(false);

        // 将ServerSocketChannel注册到Selector上,并指定感兴趣的事件为接收连接事件
        serverChannel.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("Server started.");

        while (true) {
            // Selector进行事件轮询
            selector.select();
            // 获取触发的事件集合
            Set<SelectionKey> selectedKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectedKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
                if (key.isAcceptable()) {
                    // 接收连接事件
                    handleAccept(key);
                } else if (key.isReadable()) {
                    // 可读事件
                    handleRead(key);
                }
            }
        }
    }

    private static void handleAccept(SelectionKey key) throws IOException {
        ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
        SocketChannel clientChannel = serverChannel.accept();
        clientChannel.configureBlocking(false);
        clientChannel.register(key.selector(), SelectionKey.OP_READ);
        System.out.println("Accepted new connection from: " + clientChannel.getRemoteAddress());
    }

    private static void handleRead(SelectionKey key) throws IOException {
        SocketChannel clientChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int bytesRead = clientChannel.read(buffer);

        if (bytesRead == -1) {
            System.out.println("Connection closed by client: " + clientChannel.getRemoteAddress());
            // 客户端关闭连接
            clientChannel.close();
        } else if (bytesRead > 0) {
            // 处理接收到的数据
            buffer.flip();
            byte[] data = new byte[buffer.limit()];
            buffer.get(data);
            System.out.println("Received data from " + clientChannel.getRemoteAddress() + ": " + new String(data));

            // 回写响应数据
            String response = "Response from server";
            ByteBuffer responseBuffer = ByteBuffer.wrap(response.getBytes());
            clientChannel.write(responseBuffer);
        }
    }
}

        Client端程序代码:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class Client {
    public static void main(String[] args) {
        for (int i = 0; i < 5; i++) {
            Thread clientThread = new Thread(new ClientRunnable());
            clientThread.start();
        }
    }

    static class ClientRunnable implements Runnable {
        @Override
        public void run() {
            try {
                // 创建客户端SocketChannel并连接到服务器
                SocketChannel clientChannel = SocketChannel.open();
                clientChannel.configureBlocking(false);
                clientChannel.connect(new InetSocketAddress("localhost", 8080));

                // 等待连接完成
                while (!clientChannel.finishConnect()) {
                    Thread.sleep(100);
                }

                // 发送数据到服务器
                String message = "Hello from client";
                ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
                clientChannel.write(buffer);

                // 接收服务器响应
                ByteBuffer responseBuffer = ByteBuffer.allocate(1024);
                while (clientChannel.read(responseBuffer) <= 0) {
                    // 等待服务器响应
                    Thread.sleep(100);
                }
                responseBuffer.flip();
                byte[] responseData = new byte[responseBuffer.limit()];
                responseBuffer.get(responseData);
                System.out.println( clientChannel.getLocalAddress()+"=>Received response from server: " + new String(responseData));
                // 关闭客户端连接
                clientChannel.close();
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

4. 总结

        1、阻塞(Blocking)和非阻塞(Nonblocking)描述的是线程在访问某个资源时,在该资源没有准备就绪期间的处理方式

  • 阻塞:阻塞是指在进行I/O操作时,当前线程会被挂起,等待数据的就绪或操作的完成
  • 非阻塞:非阻塞是指进行I/O操作时,当前线程不会被挂起,而是立即返回并继续执行其他任务

        2、同步(synchronous)与异步(asynchronous)描述的是线程在发出请求后,是否等待结果

  • 同步是指程序按照顺序执行,并等待某个操作完成后再继续执行下一个操作
  • 在异步操作中,程序不会阻塞等待结果的返回,而是通过回调、轮询或事件通知等机制来获取结果或处理完成的事件

        3、当涉及I/O操作时,可以根据是否阻塞和是否异步的角度将其分为以下四类

  • 阻塞式I/O(Blocking I/O)
  • 非阻塞式I/O(Non-Blocking I/O)
  • I/O多路复用(I/O Multiplexing)
  • 异步I/O(Asynchronous I/O)

        4、在Java编程中提到的BIO、NIO和AIO,一般指的是Java语言为实现不同类型的I/O操作所提供的API

  • Java IO:Java IO是JDK 1.0版本其自带的用于读取和写入数据的API,因其同步、阻塞的特征,被归类为同步阻塞式IO(Blocking IO),即Java BIO
  • Java NIO(New IO):是JDK 1.4开始提供的同步非阻塞式的IO操作API,因其同步、非阻塞的特征,开发者一般将Java NIO理解为Java Non-Blocking IO
  • Java NIO 2.0:是JDK 1.7开始提供的异步非阻塞式的IO操作API,因其是在NIO的基础上进行了改进,称为NIO 2.0;因其异步、非阻塞的特征,开发者一般将Java NIO 2.0称为Java AIO

        5、Java BIO和NIO采用了2种不同的模型

  • BIO使用了面向流(Stream Oriented)的模型
  • Java NIO使用了面向缓冲区(Buffer Oriented)的,基于通道(Channel Based)的模型

        6、Java NIO编程中的核心API包括Buffer、Channel和Selector

  • Buffer(缓冲区)是Java NIO中提供的用于存储数据的容器,底层依靠数组来存储数据,并提供了对数据的结构化访问以及维护读写位置等信息的功能
  • Channel(通道)是Java NIO中提供的用于传输数据的工具,代表了源节点和目标节点之间的数据通道
  • Selector 是 Java NIO 提供的一个组件,它可以检查一个或多个Channel 实例,并确定哪些通道准备好用于读、写等操作,通过这种方式,单个线程可以管理多个通道,从而管理多个网络连接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/577935.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Android使用AlertDialog实现弹出菜单

最近又开始捣鼓APP&#xff0c;许多api , class都忘记怎么用了&#xff0c;楼下使用AlertDialog实现个弹出菜单&#xff0c;结果直接crash&#xff0c;查了半天&#xff0c;终于即将&#xff0c;记录一下…… 1 实现代码 AlertDialog.Builder mBuilder new AlertDialog.Builde…

后端工程师——C++工程师如何准备面试?

相比 Java 语言方向,C++ 入门简单,精通难,找工作竞争压力更小,但 C++ 依然是近年来招聘的热门岗位之一。本文将从以下三个方面进行详细讲解,帮助你对 C++ 相关岗位的就业前景、岗位要求、学习路线等有更充分的了解。 C++工程师面试准备 上两篇文章对 C++ 工程师的招聘需求…

SpringCloud系列(17)--将服务消费者Consumer注册进Zookeeper

前言&#xff1a;在上一章节中我们把服务提供者Provider注册进了Zookeeper&#xff0c;而本章节则是关于如何将服务消费者Consumer注册进Zookeeper 1、再次创建一个服务提供者模块&#xff0c;命名为consumerzk-order80 (1)在父工程下新建模块 (2)选择模块的项目类型为Maven并…

HPE Aruba Networking推出新一代Wi-Fi 7接入点 助力企业高效应对安全、AI与物联网挑战

HPE ArubaNetworking推出的全新Wi-Fi 7接入点&#xff0c;提供全面的AI就绪边缘IT解决方案&#xff0c;旨在为用户和物联网设备提供安全、高性能的连接服务&#xff0c;以实现数据的捕获和路由&#xff0c;从而满足AI训练和推理需求 休斯顿-2024年4月23日-慧与科技(NYSE: HPE)近…

【golang学习之旅】深入理解字符串string数据类型

系列文章 【golang学习之旅】报错&#xff1a;a declared but not used 【golang学习之旅】Go 的基本数据类型 目录 系列文章使用示例string的底层数据结构关于字符串复制字符串是不可变的如何高效的进行字符串拼接&#xff1f; 使用示例 Go 语言中的字符串只是一个只读的字节…

Spring boot + Redis + Spring Cache 实现缓存

学习 Redis 的 value 有 5 种常用的数据结构 Redis 存储的是 key-value 结构的数据。key 是字符串类型&#xff0c;value 有 5 种常用的数据结构&#xff1a; Redis 的图形化工具 Another Redis Desktop Manager Spring Data Redis Redis 的 Java 客户端。 Spring Cache Spr…

AI工具集:解锁智能新境界,一站式解决你的所有需求!

在这个信息爆炸的时代&#xff0c;我们每天都在与大量的数据和信息打交道。如何高效地处理这些信息&#xff0c;提高工作效率和生活品质&#xff0c;成为了我们亟待解决的问题。而AI工具集(AI-321.com)的出现&#xff0c;无疑为我们提供了一把解锁智能新境界的钥匙。 AI-321 | …

VirtualBox7.0.16的蓝屏大坑与ssh登陆ubuntu虚拟机的办法

背景&#xff1a; 安装了最新版的VirtualBox&#xff0c;装了ubuntu系统&#xff0c;在win10下通过ssh死活无法与ubuntu进行正常登陆控制。 然后开始了踩坑。 问题1&#xff1a;ssh登陆失败&#xff0c;但是主机能ping通ubuntu&#xff0c;反过来也能ping通&#xff0c;网络…

地学研究相关工具推荐0426

地学研究相关工具推荐0426 文章目录 地学研究相关工具推荐0426前言工具PanoplyFileZillaGetData Graph DigitizerZotero**谷谷GIS地图下载器** 总结 前言 以下这些工具是之前在进行一些研究过程中使用过的工具&#xff0c;在之后的研究中可能会用到&#xff0c;推荐给大家&…

Unity类银河恶魔城学习记录14-5 p152 Lost currency save and enemy‘s currency drop

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili LostCurrencyController.cs using System.Collections; using System.Colle…

每天五分钟深度学习:如何理解梯度下降算法可以逼近全局最小值?

本文重点 上节课程中,我们已经知道了逻辑回归的代价函数J。要想最小化代价函数,我们需要使用梯度下降算法。 梯度下降算法地直观理解: 为了可视化,我们假设w和b都是单一实数,实际上,w可以是更高地维度。 代价函数J是在水平轴w和b上的曲面,因此曲面的高度就是J(w,b)在…

井字棋游戏

1. 游戏创建 1.1导包 from tkinter import * import numpy as np import math import tkinter.messagebox 1.2 窗口内容 1.2.1创建一个窗口 root Tk() # 窗口名称 root.title("井字棋 from Sun") 1.2.2 创建一个框架&#xff0c;将其放置在窗口中 Frame1 F…

如何进行域名解析?如何清理DNS缓存?(附源码)

目录 1、什么是域名&#xff1f; 2、为什么使用域名&#xff1f; 3、域名解析的完整流程 4、调用gethostbyname系统接口将域名解析成IP地址 5、为什么需要清理系统DNS缓存&#xff1f; 6、使用cmd命令清理DNS缓存 7、通过代码去清除系统DNS缓存 C软件异常排查从入门到精…

图像分类导论:从模型设计到端到端

书籍&#xff1a;An Introduction to Image Classification&#xff1a;From Designed Models to End-to-End Learning 作者&#xff1a;Klaus D. Toennies 出版&#xff1a;Springer Singapore 书籍下载-《图像分类导论》图像分类的传统方法包括在特征空间中进行特征提取和…

怎么提高职场辩论的口才能力的方法

提高职场辩论的口才能力是一个综合而复杂的过程&#xff0c;涉及知识积累、技巧学习、实践锻炼等多个方面。以下是关于如何提高职场辩论口才能力的详细分析和建议。 一、引言 在职场中&#xff0c;良好的口才能力对于个人职业发展具有重要意义。优秀的口才不仅能够提升个人的…

日志分析简单总结

1、分析日志的目的 误报&#xff1a;不是攻击而上报成攻击 漏报&#xff1a;是攻击而没有防御的情况 日志分析可以判断是否误判或者漏判&#xff0c;可以溯源攻击行为 在护网作为防守方必备的技能&#xff08;分析NGAF和态势感知&#xff0c;发现异常&#xff09; 2、攻击出现…

C++进阶--智能指针

智能指针的概念 智能指针是C中的一个重要概念&#xff0c;用于管理动态分配的对象内存。它是一个类模板&#xff0c;通过封装原始指针&#xff0c;并在对象生命周期结束时自动释放内存&#xff0c;从而避免了内存泄漏和资源管理的繁琐工作。 C标准库提供了多种常见的智能指针…

el-date-picker 禁用时分秒选择(包括禁用下拉框展示)

2024.04.26今天我学习了对el-date-picker进行禁用时分秒&#xff0c; 在使用el-date-picker组件的时候&#xff0c;我们有可能遇到需要把时分秒的时间固定&#xff0c;然后并且不能让他修改&#xff1a; 1714120999296 比如右上角的这个时间&#xff0c;我们要给它固定是‘08:…

Open3D(C++) 最小二乘拟合多项式曲线

目录 一、算法原理二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的爬虫与GPT。 一、算法原理 多项式曲线表示为: p ( x ) =

使用Screenshots安装Fedora 40版本详细教程

Fedora 40是Fedora操作系统的最新版本&#xff0c;于 2024 年 4 月 23 日发布&#xff0c;是一个社区支持的 Linux 发行版&#xff0c;以其创新功能、领先技术和活跃的社区支持而闻名。 在本指南中&#xff0c;我们将引导您完成安装Fedora 40 Server的分步过程&#xff0c;确保…