当前位置: 首页 > news >正文

Java知识巩固(十二)

I/O

JavaIO流了解吗?

IO 即 Input/Output,输入和输出。数据输入到计算机内存的过程即输入,反之输出到外部存储(比如数据库,文件,远程主机)的过程即输出。数据传输过程类似于水流,因此称为 IO 流。IO 流在 Java 中分为输入流和输出流,而根据数据的处理方式又分为字节流和字符流。

Java IO 流的 40 多个类都是从如下 4 个抽象类基类中派生出来的。

  • InputStream/Reader: 所有的输入流的基类,前者是字节输入流,后者是字符输入流。
  • OutputStream/Writer: 所有输出流的基类,前者是字节输出流,后者是字符输出流。

I/O流为什么要分为字节流和字符流呢?

个人认为主要有两点原因:

  • 字符流是由 Java 虚拟机将字节转换得到的,这个过程还算是比较耗时;
  • 如果我们不知道编码类型的话,使用字节流的过程中很容易出现乱码问题。

JavaIO中的设计模式有哪些?

装饰器模式

装饰器(Decorator)模式 可以在不改变原有对象的情况下拓展其功能。

装饰器模式通过组合替代继承来扩展原始类的功能,在一些继承关系比较复杂的场景(IO 这一场景各种类的继承关系就比较复杂)更加实用。

对于字节流来说, FilterInputStream (对应输入流)和FilterOutputStream(对应输出流)是装饰器模式的核心,分别用于增强 InputStreamOutputStream子类对象的功能。

我们常见的BufferedInputStream(字节缓冲输入流)、DataInputStream 等等都是FilterInputStream 的子类,BufferedOutputStream(字节缓冲输出流)、DataOutputStream等等都是FilterOutputStream的子类。

举个例子,我们可以通过 BufferedInputStream(字节缓冲输入流)来增强 FileInputStream 的功能。

BufferedInputStream 构造函数如下:

public BufferedInputStream(InputStream in) {this(in, DEFAULT_BUFFER_SIZE);
}public BufferedInputStream(InputStream in, int size) {super(in);if (size <= 0) {throw new IllegalArgumentException("Buffer size <= 0");}buf = new byte[size];
}

可以看出,BufferedInputStream 的构造函数其中的一个参数就是 InputStream 。

BufferedInputStream 代码示例:

try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("input.txt"))) {int content;long skip = bis.skip(2);while ((content = bis.read()) != -1) {System.out.print((char) content);}
} catch (IOException e) {e.printStackTrace();
}

这个时候,你可以会想了:为啥我们直接不弄一个BufferedFileInputStream(字符缓冲文件输入流)呢?

BufferedFileInputStream bfis = new BufferedFileInputStream("input.txt");

如果 InputStream的子类比较少的话,这样做是没问题的。不过, InputStream的子类实在太多,继承关系也太复杂了。如果我们为每一个子类都定制一个对应的缓冲输入流,那岂不是太麻烦了。

如果你对 IO 流比较熟悉的话,你会发现ZipInputStreamZipOutputStream 还可以分别增强 BufferedInputStreamBufferedOutputStream 的能力。

BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fileName));
ZipInputStream zis = new ZipInputStream(bis);BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));
ZipOutputStream zipOut = new ZipOutputStream(bos);

ZipInputStream 和ZipOutputStream 分别继承自InflaterInputStream 和DeflaterOutputStream

public
class InflaterInputStream extends FilterInputStream {
}public
class DeflaterOutputStream extends FilterOutputStream {
}

这也是装饰器模式很重要的一个特征,那就是可以对原始类嵌套使用多个装饰器。

为了实现这一效果,装饰器类需要跟原始类继承相同的抽象类或者实现相同的接口。上面介绍到的这些 IO 相关的装饰类和原始类共同的父类是 InputStreamOutputStream

对于字符流来说,BufferedReader 可以用来增加 Reader (字符输入流)子类的功能,BufferedWriter 可以用来增加 Writer (字符输出流)子类的功能。

 

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), "UTF-8"));

IO 流中的装饰器模式应用的例子实在是太多了,不需要特意记忆,完全没必要哈!搞清了装饰器模式的核心之后,你在使用的时候自然就会知道哪些地方运用到了装饰器模式。

适配器模式

适配器(Adapter Pattern)模式 主要用于接口互不兼容的类的协调工作,你可以将其联想到我们日常经常使用的电源适配器。

适配器模式中存在被适配的对象或者类称为 适配者(Adaptee) ,作用于适配者的对象或者类称为适配器(Adapter) 。适配器分为对象适配器和类适配器。类适配器使用继承关系来实现,对象适配器使用组合关系来实现。

IO 流中的字符流和字节流的接口不同,它们之间可以协调工作就是基于适配器模式来做的,更准确点来说是对象适配器。通过适配器,我们可以将字节流对象适配成一个字符流对象,这样我们可以直接通过字节流对象来读取或者写入字符数据。

InputStreamReaderOutputStreamWriter 就是两个适配器(Adapter), 同时,它们两个也是字节流和字符流之间的桥梁。InputStreamReader 使用 StreamDecoder (流解码器)对字节进行解码,实现字节流到字符流的转换, OutputStreamWriter 使用StreamEncoder(流编码器)对字符进行编码,实现字符流到字节流的转换。

InputStreamOutputStream 的子类是被适配者, InputStreamReaderOutputStreamWriter是适配器。

// InputStreamReader 是适配器,FileInputStream 是被适配的类
InputStreamReader isr = new InputStreamReader(new FileInputStream(fileName), "UTF-8");
// BufferedReader 增强 InputStreamReader 的功能(装饰器模式)
BufferedReader bufferedReader = new BufferedReader(isr);

java.io.InputStreamReader 部分源码:

public class InputStreamReader extends Reader {//用于解码的对象private final StreamDecoder sd;public InputStreamReader(InputStream in) {super(in);try {// 获取 StreamDecoder 对象sd = StreamDecoder.forInputStreamReader(in, this, (String)null);} catch (UnsupportedEncodingException e) {throw new Error(e);}}// 使用 StreamDecoder 对象做具体的读取工作public int read() throws IOException {return sd.read();}
}

java.io.OutputStreamWriter 部分源码:

public class OutputStreamWriter extends Writer {// 用于编码的对象private final StreamEncoder se;public OutputStreamWriter(OutputStream out) {super(out);try {// 获取 StreamEncoder 对象se = StreamEncoder.forOutputStreamWriter(out, this, (String)null);} catch (UnsupportedEncodingException e) {throw new Error(e);}}// 使用 StreamEncoder 对象做具体的写入工作public void write(int c) throws IOException {se.write(c);}
}

适配器模式和装饰器模式有什么区别呢?

装饰器模式 更侧重于动态地增强原始类的功能,装饰器类需要跟原始类继承相同的抽象类或者实现相同的接口。并且,装饰器模式支持对原始类嵌套使用多个装饰器。

适配器模式 更侧重于让接口不兼容而不能交互的类可以一起工作,当我们调用适配器对应的方法时,适配器内部会调用适配者类或者和适配类相关的类的方法,这个过程透明的。就比如说 StreamDecoder (流解码器)和StreamEncoder(流编码器)就是分别基于 InputStreamOutputStream 来获取 FileChannel对象并调用对应的 read 方法和 write 方法进行字节数据的读取和写入。

StreamDecoder(InputStream in, Object lock, CharsetDecoder dec) {// 省略大部分代码// 根据 InputStream 对象获取 FileChannel 对象ch = getChannel((FileInputStream)in);
}

适配器和适配者两者不需要继承相同的抽象类或者实现相同的接口。

另外,FutureTask 类使用了适配器模式,Executors 的内部类 RunnableAdapter 实现属于适配器,用于将 Runnable 适配成 Callable

FutureTask参数包含 Runnable 的一个构造方法:

public FutureTask(Runnable runnable, V result) {// 调用 Executors 类的 callable 方法this.callable = Executors.callable(runnable, result);this.state = NEW;
}

Executors中对应的方法和适配器:

// 实际调用的是 Executors 的内部类 RunnableAdapter 的构造方法
public static <T> Callable<T> callable(Runnable task, T result) {if (task == null)throw new NullPointerException();return new RunnableAdapter<T>(task, result);
}
// 适配器
static final class RunnableAdapter<T> implements Callable<T> {final Runnable task;final T result;RunnableAdapter(Runnable task, T result) {this.task = task;this.result = result;}public T call() {task.run();return result;}
}

工厂模式

工厂模式用于创建对象,NIO 中大量用到了工厂模式,比如 Files 类的 newInputStream 方法用于创建 InputStream 对象(静态工厂)、 Paths 类的 get 方法创建 Path 对象(静态工厂)、ZipFileSystem 类(sun.nio包下的类,属于 java.nio 相关的一些内部实现)的 getPath 的方法创建 Path 对象(简单工厂)。

InputStream is = Files.newInputStream(Paths.get(generatorLogoPath))

观察者模式

NIO 中的文件目录监听服务使用到了观察者模式。

NIO 中的文件目录监听服务基于 WatchService 接口和 Watchable 接口。WatchService 属于观察者,Watchable 属于被观察者。

Watchable 接口定义了一个用于将对象注册到 WatchService(监控服务) 并绑定监听事件的方法 register

public interface Pathextends Comparable<Path>, Iterable<Path>, Watchable{
}public interface Watchable {WatchKey register(WatchService watcher,WatchEvent.Kind<?>[] events,WatchEvent.Modifier... modifiers)throws IOException;
}

WatchService 用于监听文件目录的变化,同一个 WatchService 对象能够监听多个文件目录。

// 创建 WatchService 对象
WatchService watchService = FileSystems.getDefault().newWatchService();// 初始化一个被监控文件夹的 Path 类:
Path path = Paths.get("workingDirectory");
// 将这个 path 对象注册到 WatchService(监控服务) 中去
WatchKey watchKey = path.register(
watchService, StandardWatchEventKinds...);

Path 类 register 方法的第二个参数 events (需要监听的事件)为可变长参数,也就是说我们可以同时监听多种事件。

WatchKey register(WatchService watcher,WatchEvent.Kind<?>... events)throws IOException;

常用的监听事件有 3 种:

  • StandardWatchEventKinds.ENTRY_CREATE:文件创建。
  • StandardWatchEventKinds.ENTRY_DELETE : 文件删除。
  • StandardWatchEventKinds.ENTRY_MODIFY : 文件修改。

register 方法返回 WatchKey 对象,通过WatchKey 对象可以获取事件的具体信息比如文件目录下是创建、删除还是修改了文件、创建、删除或者修改的文件的具体名称是什么。

WatchKey key;
while ((key = watchService.take()) != null) {for (WatchEvent<?> event : key.pollEvents()) {// 可以调用 WatchEvent 对象的方法做一些事情比如输出事件的具体上下文信息}key.reset();
}

WatchService 内部是通过一个 daemon thread(守护线程)采用定期轮询的方式来检测文件的变化,简化后的源码如下所示。

class PollingWatchServiceextends AbstractWatchService
{// 定义一个 daemon thread(守护线程)轮询检测文件变化private final ScheduledExecutorService scheduledExecutor;PollingWatchService() {scheduledExecutor = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread t = new Thread(r);t.setDaemon(true);return t;}});}void enable(Set<? extends WatchEvent.Kind<?>> events, long period) {synchronized (this) {// 更新监听事件this.events = events;// 开启定期轮询Runnable thunk = new Runnable() { public void run() { poll(); }};this.poller = scheduledExecutor.scheduleAtFixedRate(thunk, period, period, TimeUnit.SECONDS);}}
}

BIO、NIO和AIO的区别?

何为I/O?

I/O(Input/Output) 即输入/输出 。

我们先从计算机结构的角度来解读一下 I/O。

根据冯.诺依曼结构,计算机结构分为 5 大部分:运算器、控制器、存储器、输入设备、输出设备。

输入设备(比如键盘)和输出设备(比如显示器)都属于外部设备。网卡、硬盘这种既可以属于输入设备,也可以属于输出设备。

输入设备向计算机输入数据,输出设备接收计算机输出的数据。

从计算机结构的视角来看的话, I/O 描述了计算机系统与外部设备之间通信的过程。

我们再先从应用程序的角度来解读一下 I/O。

根据大学里学到的操作系统相关的知识:为了保证操作系统的稳定性和安全性,一个进程的地址空间划分为 用户空间(User space)内核空间(Kernel space )

像我们平常运行的应用程序都是运行在用户空间,只有内核空间才能进行系统态级别的资源有关的操作,比如文件管理、进程通信、内存管理等等。也就是说,我们想要进行 IO 操作,一定是要依赖内核空间的能力。

并且,用户空间的程序不能直接访问内核空间。

当想要执行 IO 操作时,由于没有执行这些操作的权限,只能发起系统调用请求操作系统帮忙完成。

因此,用户进程想要执行 IO 操作的话,必须通过 系统调用 来间接访问内核空间

我们在平常开发过程中接触最多的就是 磁盘 IO(读写文件)网络 IO(网络请求和响应)

从应用程序的视角来看的话,我们的应用程序对操作系统的内核发起 IO 调用(系统调用),操作系统负责的内核执行具体的 IO 操作。也就是说,我们的应用程序实际上只是发起了 IO 操作的调用而已,具体 IO 的执行是由操作系统的内核来完成的。

当应用程序发起 I/O 调用后,会经历两个步骤:

  1. 内核等待 I/O 设备准备好数据
  2. 内核将数据从内核空间拷贝到用户空间。

有哪些常见的IO模型?

UNIX 系统下, IO 模型一共有 5 种:同步阻塞 I/O同步非阻塞 I/OI/O 多路复用信号驱动 I/O 和异步 I/O

这也是我们经常提到的 5 种 IO 模型。

Java中3重常见IO模型

BIO 属于同步阻塞 IO 模型 。

同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到内核把数据拷贝到用户空间。

在客户端连接数量不高的情况下,是没问题的。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

NIO (Non-blocking/New I/O)

Java 中的 NIO 于 Java 1.4 中引入,对应 java.nio 包,提供了 Channel , SelectorBuffer 等抽象。NIO 中的 N 可以理解为 Non-blocking,不单纯是 New。它是支持面向缓冲的,基于通道的 I/O 操作方法。 对于高负载、高并发的(网络)应用,应使用 NIO 。

Java 中的 NIO 可以看作是 I/O 多路复用模型。也有很多人认为,Java 中的 NIO 属于同步非阻塞 IO 模型。

跟着我的思路往下看看,相信你会得到答案!

我们先来看看 同步非阻塞 IO 模型

同步非阻塞 IO 模型中,应用程序会一直发起 read 调用,等待数据从内核空间拷贝到用户空间的这段时间里,线程依然是阻塞的,直到在内核把数据拷贝到用户空间。

相比于同步阻塞 IO 模型,同步非阻塞 IO 模型确实有了很大改进。通过轮询操作,避免了一直阻塞。

但是,这种 IO 模型同样存在问题:应用程序不断进行 I/O 系统调用轮询数据是否已经准备好的过程是十分消耗 CPU 资源的。

这个时候,I/O 多路复用模型 就上场了。

IO 多路复用模型中,线程首先发起 select 调用,询问内核数据是否准备就绪,等内核把数据准备好了,用户线程再发起 read 调用。read 调用的过程(数据从内核空间 -> 用户空间)还是阻塞的。

目前支持 IO 多路复用的系统调用,有 select,epoll 等等。select 系统调用,目前几乎在所有的操作系统上都有支持。

  • select 调用:内核提供的系统调用,它支持一次查询多个系统调用的可用状态。几乎所有的操作系统都支持。
  • epoll 调用:linux 2.6 内核,属于 select 调用的增强版本,优化了 IO 的执行效率。

IO 多路复用模型,通过减少无效的系统调用,减少了对 CPU 资源的消耗。

Java 中的 NIO ,有一个非常重要的选择器 ( Selector ) 的概念,也可以被称为 多路复用器。通过它,只需要一个线程便可以管理多个客户端连接。当客户端数据到了之后,才会为其服务。

        

AIO(AsynchronousI/O)

AIO 也就是 NIO 2。Java 7 中引入了 NIO 的改进版 NIO 2,它是异步 IO 模型。

异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

目前来说 AIO 的应用还不是很广泛。Netty 之前也尝试使用过 AIO,不过又放弃了。这是因为,Netty 使用了 AIO 之后,在 Linux 系统上的性能并没有多少提升。

最后,来一张图,简单总结一下 Java 中的 BIO、NIO、AIO。

I/O

何为 I/O?

I/O(Input/Output) 即输入/输出 。

我们先从计算机结构的角度来解读一下 I/O。

根据冯.诺依曼结构,计算机结构分为 5 大部分:运算器、控制器、存储器、输入设备、输出设备。

冯诺依曼体系结构

冯诺依曼体系结构

输入设备(比如键盘)和输出设备(比如显示器)都属于外部设备。网卡、硬盘这种既可以属于输入设备,也可以属于输出设备。

输入设备向计算机输入数据,输出设备接收计算机输出的数据。

从计算机结构的视角来看的话, I/O 描述了计算机系统与外部设备之间通信的过程。

我们再先从应用程序的角度来解读一下 I/O。

根据大学里学到的操作系统相关的知识:为了保证操作系统的稳定性和安全性,一个进程的地址空间划分为 用户空间(User space) 和 内核空间(Kernel space ) 。

像我们平常运行的应用程序都是运行在用户空间,只有内核空间才能进行系统态级别的资源有关的操作,比如文件管理、进程通信、内存管理等等。也就是说,我们想要进行 IO 操作,一定是要依赖内核空间的能力。

并且,用户空间的程序不能直接访问内核空间。

当想要执行 IO 操作时,由于没有执行这些操作的权限,只能发起系统调用请求操作系统帮忙完成。

因此,用户进程想要执行 IO 操作的话,必须通过 系统调用 来间接访问内核空间

我们在平常开发过程中接触最多的就是 磁盘 IO(读写文件) 和 网络 IO(网络请求和响应)

从应用程序的视角来看的话,我们的应用程序对操作系统的内核发起 IO 调用(系统调用),操作系统负责的内核执行具体的 IO 操作。也就是说,我们的应用程序实际上只是发起了 IO 操作的调用而已,具体 IO 的执行是由操作系统的内核来完成的。

当应用程序发起 I/O 调用后,会经历两个步骤:

  1. 内核等待 I/O 设备准备好数据
  2. 内核将数据从内核空间拷贝到用户空间。

有哪些常见的 IO 模型?

UNIX 系统下, IO 模型一共有 5 种:同步阻塞 I/O同步非阻塞 I/OI/O 多路复用信号驱动 I/O 和异步 I/O

这也是我们经常提到的 5 种 IO 模型。

Java 中 3 种常见 IO 模型

BIO (Blocking I/O)

BIO 属于同步阻塞 IO 模型 。

同步阻塞 IO 模型中,应用程序发起 read 调用后,会一直阻塞,直到内核把数据拷贝到用户空间。

图源:《深入拆解Tomcat & Jetty》

图源:《深入拆解Tomcat & Jetty》

在客户端连接数量不高的情况下,是没问题的。但是,当面对十万甚至百万级连接的时候,传统的 BIO 模型是无能为力的。因此,我们需要一种更高效的 I/O 处理模型来应对更高的并发量。

NIO (Non-blocking/New I/O)

Java 中的 NIO 于 Java 1.4 中引入,对应 java.nio 包,提供了 Channel , SelectorBuffer 等抽象。NIO 中的 N 可以理解为 Non-blocking,不单纯是 New。它是支持面向缓冲的,基于通道的 I/O 操作方法。 对于高负载、高并发的(网络)应用,应使用 NIO 。

Java 中的 NIO 可以看作是 I/O 多路复用模型。也有很多人认为,Java 中的 NIO 属于同步非阻塞 IO 模型。

跟着我的思路往下看看,相信你会得到答案!

我们先来看看 同步非阻塞 IO 模型

图源:《深入拆解Tomcat & Jetty》

图源:《深入拆解Tomcat & Jetty》

同步非阻塞 IO 模型中,应用程序会一直发起 read 调用,等待数据从内核空间拷贝到用户空间的这段时间里,线程依然是阻塞的,直到在内核把数据拷贝到用户空间。

相比于同步阻塞 IO 模型,同步非阻塞 IO 模型确实有了很大改进。通过轮询操作,避免了一直阻塞。

但是,这种 IO 模型同样存在问题:应用程序不断进行 I/O 系统调用轮询数据是否已经准备好的过程是十分消耗 CPU 资源的。

这个时候,I/O 多路复用模型 就上场了。

 

IO 多路复用模型中,线程首先发起 select 调用,询问内核数据是否准备就绪,等内核把数据准备好了,用户线程再发起 read 调用。read 调用的过程(数据从内核空间 -> 用户空间)还是阻塞的。

目前支持 IO 多路复用的系统调用,有 select,epoll 等等。select 系统调用,目前几乎在所有的操作系统上都有支持。

  • select 调用:内核提供的系统调用,它支持一次查询多个系统调用的可用状态。几乎所有的操作系统都支持。
  • epoll 调用:linux 2.6 内核,属于 select 调用的增强版本,优化了 IO 的执行效率。

IO 多路复用模型,通过减少无效的系统调用,减少了对 CPU 资源的消耗。

Java 中的 NIO ,有一个非常重要的选择器 ( Selector ) 的概念,也可以被称为 多路复用器。通过它,只需要一个线程便可以管理多个客户端连接。当客户端数据到了之后,才会为其服务。

Buffer、Channel和Selector三者之间的关系

Buffer、Channel和Selector三者之间的关系

AIO (Asynchronous I/O)

AIO 也就是 NIO 2。Java 7 中引入了 NIO 的改进版 NIO 2,它是异步 IO 模型。

异步 IO 是基于事件和回调机制实现的,也就是应用操作之后会直接返回,不会堵塞在那里,当后台处理完成,操作系统会通知相应的线程进行后续的操作。

 

目前来说 AIO 的应用还不是很广泛。Netty 之前也尝试使用过 AIO,不过又放弃了。这是因为,Netty 使用了 AIO 之后,在 Linux 系统上的性能并没有多少提升。

相关文章:

Java知识巩固(十二)

I/O JavaIO流了解吗&#xff1f; IO 即 Input/Output&#xff0c;输入和输出。数据输入到计算机内存的过程即输入&#xff0c;反之输出到外部存储&#xff08;比如数据库&#xff0c;文件&#xff0c;远程主机&#xff09;的过程即输出。数据传输过程类似于水流&#xff0c;因…...

一家光伏企业终止,恐不具行业代表性,市占率仅为2.35%

海达光能终止原因如下&#xff1a;报告期内海达光能销售金额较所在行业第二名亚玛顿相差两倍以上&#xff0c;公司毛利率更是远低于行业龙头福莱特&#xff0c;恐难以说明公司行业代表性。在企业竞争上&#xff0c;公司2021年度的市场占有率约为2.35%&#xff0c;公司未来光伏玻…...

企业计算机监控软件是什么?6款电脑监控软件分享!提升企业管理效率,吐血推荐!

嘿&#xff0c;各位企业管理者和IT小伙伴们&#xff01; 您是否曾担忧员工在工作时间内效率低下&#xff1f;是否对公司的数据安全感到不安&#xff1f; 别担心&#xff0c;今天我们就来聊聊企业计算机监控软件&#xff0c;它就像是企业的"超级侦探"&#xff0c;帮…...

VisionPro —— CogOCRMaxTool工具详解

CogOCRMaxTool的作用&#xff1a; CogOCRMaxTool:是一个字符识别工具&#xff0c;主要用于字符识别,它能够根据已训练的字符样本读取灰度图像中的字符,并返回读取结果。 一&#xff1a;工具位置 二&#xff1a;添加图片 三&#xff1a;工具的初始页面 将识别框拖到需要识别处…...

网站安全问题都有哪些,分别详细说明

网站安全问题涉及多个方面&#xff0c;以下是一些常见的网站安全问题及其详细说明&#xff1a; 数据泄露 问题描述&#xff1a;数据泄露是指网站存储的用户敏感信息&#xff08;如用户名、密码、信用卡信息等&#xff09;被非法获取。黑客可能通过SQL注入、XSS攻击等手段窃取这…...

DiskGenius一键修复磁盘损坏

下午外接磁盘和U盘都出现扇区损坏&#xff0c;估计就是在开着电脑&#xff0c;可能是电脑运行的软件还在对磁盘进行读写&#xff0c;不小心按到笔记本关机键&#xff0c;重新开机读写磁盘分区变得异常卡顿&#xff0c;估摸就是这个原因导致扇区损坏。在进行读写时&#xff0c;整…...

Matlab实现鼠群优化算法优化回声状态网络模型 (ROS-ESN)(附源码)

目录 1.内容介绍 2.部分代码 3.实验结果 4.内容获取 1内容介绍 鼠群优化算法&#xff08;Rat Swarm Optimization, ROS&#xff09;是一种基于老鼠群体行为的群体智能优化算法。ROS通过模拟老鼠在寻找食物时的聚集、分散和跟随行为&#xff0c;来探索解空间并寻找最优解。该算…...

nfs作业

一、作业要求 1、开放/nfs/shared目录&#xff0c;供所有用户查询资料 2、开放/nfs/upload目录&#xff0c;为192.168.xxx.0/24网段主机可以上传目录&#xff0c; 并将所有用户及所属的组映射为nfs-upload,其UID和GID均为210 3、将/home/tom目录仅共享给192.168.xxx.xxx这台…...

Linux 基础io_理解文件系统_软硬链接_动静态库

一.磁盘 1.磁盘物理结构 盘片 磁盘可以有多个磁片&#xff0c;每个磁片有两个盘面&#xff0c;每个盘面都对应一个磁头&#xff0c;都可以存储数据。 磁道 扇区 磁道是指在盘面上&#xff0c;由磁头读写的数据环形轨道。每个磁道都是由一圈圈的圆形区域组成&#xff0c;数据…...

大语言模型参数传递、model 构建与tokenizer构建(基于llama3模型)

文章目录 前言一、传递参数构建1、构建模型参数2、构建数据参数3、构建训练参数4、类似parse方式解析数据、模型、训练参数五、构建tokenizer与model1、tokenizer与model调用代码2、tokenizer实现2、model实现前言 上一篇说到huggingface的参数传递理论方法,本篇文章应用与ll…...

使用 `screen` + `nohup` 实现高效日志记录和多环境任务管理

使用 screen nohup 实现高效日志记录和多环境任务管理 在深度学习模型训练中&#xff0c;特别是在服务器上运行长时间的任务时&#xff0c;有效的任务管理和日志记录至关重要。我们通常需要在后台运行多个任务&#xff0c;同时为每个任务配置不同的 conda 环境。通过结合使用…...

【探索数字孪生,引领未来技术】

在数字化浪潮的推动下&#xff0c;数字孪生技术正成为连接虚拟与现实的桥梁&#xff0c;它不仅是工业互联网的基石&#xff0c;更是智慧城市、智慧园区、智慧楼宇以及元宇宙构建的核心。为了帮助更多专业人士掌握这一前沿技术&#xff0c;我们荣幸地宣布&#xff0c;“新质技术…...

Tcp_Sever(线程池版本的 TCP 服务器)

Tcp_Sever&#xff08;线程池版本的 TCP 服务器&#xff09; 前言1. 功能介绍及展示1.1 服务端连接1.2 客户端连接&#xff08;可多个用户同时在线连接服务端&#xff09;1.3 功能服务1.3.1 defaultService&#xff08;默认服务&#xff09;1.3.2 transform&#xff08;大小写转…...

第十一章 Vue生命周期及生命周期的四个阶段

目录 一、引言 1.1. Vue生命周期的具体阶段 1.2. 每个阶段的具体作用和常用场景 1.3. 生命周期钩子函数 ​二、代码示例 三、运行效果 一、引言 Vue生命周期是指Vue组件实例从创建到销毁的整个过程。在这个过程中&#xff0c;组件经历了一系列的阶段&#xff0c;每个阶段…...

展厅展会客流显示屏的客流统计功能如何实现

随着科技的发展&#xff0c;展厅和展会的管理越来越智能化。客流显示屏作为一种高效的管理工具&#xff0c;能够实时显示参观人数&#xff0c;帮助主办方更好地了解客流情况&#xff0c;优化资源配置。本文将详细介绍展厅展会客流显示屏的客流统计功能如何实现&#xff0c;分为…...

golang正则表达式的使用及举例

正则表达式很强大&#xff0c;在一些场合如抓包&#xff0c;爬虫等方面很有用。在 Go语言中&#xff0c;正则表达式通过标准库 regexp 提供支持。使用正则表达式可以进行字符串匹配、替换和分割等操作。 以下是正则表达式的基本使用方法及示例&#xff1a; 1. 导入 regexp 包 …...

Flutter杂学: iOS 上启用自动填充和关联域

下面是详细的配置和代码&#xff0c;以确保在 iOS 上启用自动填充和关联域&#xff08;Associated Domains&#xff09;功能。 配置步骤 1. 在 Apple Developer 控制台中启用 Associated Domains 登录 Apple Developer。导航至您的 App ID 设置页面。找到您要配置的 App ID&…...

接口自动化-框架搭建(Python+request+pytest+allure)

使用代码如何开展接口自动化测试。 一 选择自动化测试用例 业务流程优先&#xff0c;单接口靠后&#xff0c;功能稳定优先&#xff0c;变更频繁不选。 二 搭建自动化测试环境 &#xff08;1&#xff09;安装python编译器3.7版本以上--自行安装 &#xff08;2&#xff09;安…...

[论文阅读]Constrained Decision Transformer for Offline Safe Reinforcement Learning

Constrained Decision Transformer for Offline Safe Reinforcement Learning Proceedings of the 40th International Conference on Machine Learning (ICML), July 23-29, 2023 https://arxiv.org/abs/2302.07351 泛读只需要了解其核心思想即可。 安全强化学习(Safe Rei…...

工具_Nginx

文章目录 location语法介绍跨域配置https配置http重定向到https配置反向代理配置负载均衡配置upstream配置负载均衡算法&#xff08;1&#xff09;rr轮询&#xff08;默认&#xff09;&#xff08;2&#xff09;wrr加权轮询&#xff08;weight&#xff09;&#xff08;3&#x…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)

概述 在 Swift 开发语言中&#xff0c;各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过&#xff0c;在涉及到多个子类派生于基类进行多态模拟的场景下&#xff0c;…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

【快手拥抱开源】通过快手团队开源的 KwaiCoder-AutoThink-preview 解锁大语言模型的潜力

引言&#xff1a; 在人工智能快速发展的浪潮中&#xff0c;快手Kwaipilot团队推出的 KwaiCoder-AutoThink-preview 具有里程碑意义——这是首个公开的AutoThink大语言模型&#xff08;LLM&#xff09;。该模型代表着该领域的重大突破&#xff0c;通过独特方式融合思考与非思考…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

【LeetCode】3309. 连接二进制表示可形成的最大数值(递归|回溯|位运算)

LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 题目描述解题思路Java代码 题目描述 题目链接&#xff1a;LeetCode 3309. 连接二进制表示可形成的最大数值&#xff08;中等&#xff09; 给你一个长度为 3 的整数数组 nums。 现以某种顺序 连接…...