深入探索Java BIO与NIO输入输出模型:基于文件复制和socket通信

在Java中,处理I/O(输入/输出)操作的方式经历了从BIO(Blocking I/O,阻塞式I/O)到NIO(New I/O 或 Non-blocking I/O,新I/O或非阻塞式I/O)的演变。这两种模型在设计和使用上有显著的区别,它们分别适用于不同的应用场景。本文将深入探讨这两种I/O模型的原理、区别以及各自的使用场景。

一、Java BIO(Blocking I/O)

Java BIO是一种同步阻塞的I/O模型,它是Java最早提供的I/O模型。在进行读写操作的时候,若使用BIO进行通信,则操作不再受到操作系统的控制,而是由应用程序自己控制。在BIO中,数据的读取写入必须阻塞在一个线程内等待其完成。

  • BIO的工作原理相对简单:当一个连接建立后,服务端会为每个连接创建一个新的线程进行处理,直到连接关闭。这种方式在并发连接数较少时表现良好,但当并发连接数增加时,由于每个连接都需要一个独立的线程,系统的资源消耗会急剧增加,导致性能下降。

  • BIO的另一个特点是它是面向流的,即一次只能处理一个输入或输出请求,且这些请求是单向的。这种处理方式在某些场景下可能不够灵活。
    在这里插入图片描述

二、Java NIO(New I/O 或 Non-blocking I/O)

Java NIO是一种同步非阻塞的I/O模型,它引入了多路复用器和缓冲区的概念,使得一个线程可以处理多个连接,提高了系统的吞吐量和性能。

  • NIO的核心组件包括Channel(通道)、Buffer(缓冲区)和Selector(选择器)。Channel类似于BIO中的流,但它可以进行双向操作,并且支持异步读写。Buffer是NIO中的数据容器,它用于在Channel中进行数据的读写操作。Selector则是NIO中的多路复用器,它可以同时监听多个Channel的状态,当Channel有数据可读或可写时,Selector会通知相应的线程进行处理。

JAVA中Buffer和Channel实现:
在这里插入图片描述

在这里插入图片描述

  • NIO的工作原理是基于Reactor模式(反应堆模式)的。当一个连接建立后,服务端会将该连接注册到Selector上,并指定感兴趣的事件(如读事件、写事件等)。然后,服务端会启动一个或多个线程不断轮询Selector,检查是否有感兴趣的事件发生。如果有事件发生,线程会处理相应的事件,然后继续轮询。这种方式使得一个线程可以处理多个连接,降低了系统的资源消耗。
    在这里插入图片描述

三、BIO与NIO的区别

  • 同步与异步:BIO是同步的,读写操作必须等待数据准备好后才能进行;而NIO是同步非阻塞的,读写操作不再受到数据准备状态的限制,可以进行读写操作,但可能需要等待数据真正写入或读取完成。

  • 阻塞与非阻塞:BIO是阻塞的,在进行读写操作的时候,若使用BIO进行通信,则操作必须阻塞在一个线程内等待其完成;而NIO是非阻塞的,在进行读写操作的时候,若使用NIO进行通信,则操作不再受到阻塞的限制,可以进行其他操作。

  • 面向流与面向缓冲:BIO是面向流的,一次只能处理一个输入或输出请求;而NIO是面向缓冲区的,一次可以处理多个输入或输出请求。

  • 选择器(Selector):NIO有选择器,而BIO没有。选择器能够检测多个注册的通道上是否有事件发生,如果有事件发生便获取事件然后针对每个事件进行相应的响应处理,这样就可以只用一个单线程去管理多个通道,也就是管理多个连接。

四、为什么说BIO是同步阻塞,而NIO是同步非阻塞

1、BIO(Blocking I/O)为什么是同步阻塞的?

  • 同步:在BIO模型中,当应用程序发起一个I/O请求(例如读取或写入数据)时,它必须等待操作系统内核完成这个请求。在此期间,应用程序的线程是阻塞的,不能做其他事情,直到I/O操作完成。这种等待内核响应的行为被称为同步。
  • 阻塞:由于应用程序的线程在等待I/O操作完成期间不能做其他工作,因此我们说这个线程是被阻塞的。阻塞意味着线程不能继续执行后续的代码或处理其他任务,直到当前的I/O操作完成。

2、NIO(New I/O 或 Non-blocking I/O)为什么是同步非阻塞的?

  • 同步:在NIO模型中,虽然引入了新的机制和概念(如选择器、通道和缓冲区),但I/O操作仍然是同步的。这意味着当应用程序发起一个I/O请求时,它仍然需要等待操作系统内核处理这个请求。NIO的同步性体现在它并没有完全消除等待,但改变了等待的方式和效率。
  • 非阻塞:与BIO不同,NIO模型通过使用选择器和通道,允许单个线程处理多个I/O通道。当一个通道上的I/O操作不再受到阻塞的限制时(例如,可以立即返回而不是等待操作完成),我们说它是非阻塞的。这并不意味着I/O操作本身不需要时间,而是说在等待操作完成的过程中,线程可以转而处理其他通道的I/O操作或执行其他任务。

BIO模型因其简单的编程模型和直观的控制流程而易于理解和使用,但在处理大量并发连接时可能会因为每个连接都需要一个线程而变得效率低下。

NIO模型通过引入选择器和通道,使得单个线程可以处理多个连接,从而提高了系统的吞吐量和可伸缩性。虽然NIO的编程模型相对复杂,但它为处理高并发和大数据量的场景提供了更有效的解决方案。

五、BIO实现文件复制

使用BIO(Blocking I/O,阻塞式I/O)模型实现文件复制涉及到使用FileInputStream和FileOutputStream类。以下例展示了如何使用BIO复制文件:

import java.io.FileInputStream;  
import java.io.FileOutputStream;  
import java.io.IOException;  public class FileCopyBIO {  public static void main(String[] args) {  String sourceFilePath = "path/to/source/file.txt";  String targetFilePath = "path/to/target/file.txt";  try (FileInputStream inputStream = new FileInputStream(sourceFilePath);  FileOutputStream outputStream = new FileOutputStream(targetFilePath)) {  byte[] buffer = new byte[1024]; // 缓冲区,用于临时存储读取的数据  int bytesRead;  // 读取源文件,并写入目标文件  while ((bytesRead = inputStream.read(buffer)) != -1) {  outputStream.write(buffer, 0, bytesRead);  }  System.out.println("File copied successfully!");  } catch (IOException e) {  e.printStackTrace();  }  }  
}

在这个例子中,我们创建了一个FileInputStream对象来读取源文件,和一个FileOutputStream对象来写入目标文件。我们使用一个字节数组buffer作为缓冲区,来临时存储从源文件读取的数据。while循环会持续读取数据,直到没有更多数据可读(即read方法返回-1)。

每次调用inputStream.read(buffer)时,它会阻塞直到有一些数据可以读取,或者到达文件末尾。同样地,outputStream.write(buffer, 0, bytesRead)也会阻塞直到所有数据都被写入。

这个简单的例子演示了BIO的基本工作方式:它会阻塞等待I/O操作的完成。在高并发或大数据量的场景下,这种阻塞行为可能会成为性能瓶颈,这时可能需要考虑使用NIO(Non-blocking I/O)或其他更高效的I/O模型。

六、NIO实现文件复制

Java NIO实现文件复制,使用FileChannel和ByteBuffer来以流的方式处理文件,适合处理大文件,因为它不会一次性将整个文件加载到内存中。

import java.io.IOException;  
import java.nio.ByteBuffer;  
import java.nio.channels.FileChannel;  
import java.nio.file.Files;  
import java.nio.file.Path;  
import java.nio.file.Paths;  
import java.nio.file.StandardOpenOption;  public class FileCopyWithNIO {  public static void main(String[] args) {  // 源文件路径  Path sourcePath = Paths.get("source.txt");  // 目标文件路径  Path destinationPath = Paths.get("destination.txt");  try {  // 打开源文件以进行读取,并获取其FileChannel  FileChannel sourceChannel = FileChannel.open(sourcePath, StandardOpenOption.READ);  // 打开(或创建)目标文件以进行写入,并获取其FileChannel  // 注意:使用TRY_WITH_RESOURCES需要确保sourceChannel和destinationChannel都实现了AutoCloseable接口  // 这里我们手动关闭它们,所以没有使用TRY_WITH_RESOURCES  FileChannel destinationChannel = FileChannel.open(destinationPath, StandardOpenOption.CREATE, StandardOpenOption.WRITE);  // 分配一个ByteBuffer来存储从源文件中读取的数据  ByteBuffer buffer = ByteBuffer.allocate(1024); // 缓冲区大小可以根据需要调整  // 读取并复制文件内容  while (sourceChannel.read(buffer) != -1) {  // 切换ByteBuffer为读模式,准备从buffer中读取数据  buffer.flip();  // 将数据写入目标文件  destinationChannel.write(buffer);  // 清空buffer,准备下一次读取  buffer.clear();  }  // 关闭文件通道  sourceChannel.close();  destinationChannel.close();  System.out.println("File copied successfully.");  } catch (IOException e) {  System.err.println("Error occurred while copying file: " + e.getMessage());  }  }  
}
  • 我们首先指定了源文件和目标文件的路径。
  • 使用FileChannel.open()方法打开源文件进行读取,并打开(或创建)目标文件进行写入。
  • 分配一个ByteBuffer来作为数据传输的中介。这个缓冲区的大小可以根据需要进行调整;在这里,我们选择了一个1024字节的缓冲区。
  • 使用一个while循环来持续从源文件中读取数据,直到文件末尾。在每次循环中:
  • 使用sourceChannel.read(buffer)方法读取数据到缓冲区。
  • 调用buffer.flip()来准备从缓冲区中读取刚刚写入的数据。这一步是必需的,因为buffer在写模式后需要切换到读模式。
  • 使用destinationChannel.write(buffer)方法将缓冲区中的数据写入目标文件。
  • 调用buffer.clear()来清空缓冲区,准备下一次读取操作。这一步不会真正清除缓冲区中的数据,而是将缓冲区的位置设置为0,并将限制设置为容量,以便下一次写入操作。
  • 关闭源文件和目标文件的通道。

这个例子展示了如何使用Java NIO的FileChannel和ByteBuffer以高效的方式复制文件,特别适用于处理大文件,因为它不需要一次性加载整个文件到内存中。

七、BIO实现socket通信

使用BIO(Blocking I/O,阻塞式I/O)实现socket通信涉及到ServerSocket和Socket类。下面是一个简单的例子,展示如何使用BIO实现一个基本的服务器-客户端socket通信。
在这里插入图片描述

服务器端(Server)

import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.io.PrintWriter;  
import java.net.ServerSocket;  
import java.net.Socket;  public class BIOServer {  public static void main(String[] args) {  int port = 8080;  try (ServerSocket serverSocket = new ServerSocket(port)) {  System.out.println("Server is listening on port " + port);  while (true) {  Socket clientSocket = serverSocket.accept(); // 阻塞等待客户端连接  System.out.println("Client connected from " + clientSocket.getInetAddress());  // 启动一个新线程来处理客户端请求  new Thread(() -> handleClient(clientSocket)).start();  }  } catch (IOException e) {  System.err.println("Could not listen on port " + port);  e.printStackTrace();  }  }  private static void handleClient(Socket clientSocket) {  try (BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));  PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true)) {  String clientMessage;  while ((clientMessage = in.readLine()) != null) { // 阻塞等待客户端消息  System.out.println("Received message from client: " + clientMessage);  out.println("Echo from server: " + clientMessage); // 发送响应给客户端  }  } catch (IOException e) {  System.err.println("Error handling client: " + e.getMessage());  } finally {  try {  clientSocket.close();  } catch (IOException e) {  e.printStackTrace();  }  }  }  
}

客户端(Client)

import java.io.BufferedReader;  
import java.io.IOException;  
import java.io.InputStreamReader;  
import java.io.PrintWriter;  
import java.net.Socket;  public class BIOClient {  public static void main(String[] args) {  String host = "localhost";  int port = 8080;  try (Socket socket = new Socket(host, port)) {  System.out.println("Connected to server at " + host + ":" + port);  // 发送消息给服务器  PrintWriter out = new PrintWriter(socket.getOutputStream(), true);  BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));  BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));  String userInput;  while ((userInput = stdIn.readLine()) != null) {  out.println(userInput);  String serverResponse = in.readLine(); // 阻塞等待服务器响应  System.out.println("Server response: " + serverResponse);  if (userInput.equalsIgnoreCase("bye")) {  break;  }  }  } catch (IOException e) {  System.err.println("Couldn't connect to server at " + host + ":" + port);  e.printStackTrace();  }  }  
}

在这个例子中,服务器使用ServerSocket监听8080端口。当客户端连接时,serverSocket.accept()方法会阻塞,直到有客户端连接上。一旦连接建立,服务器会为新连接的客户端启动一个新线程来处理通信。

客户端使用Socket类连接到服务器。客户端和服务器都使用BufferedReader和PrintWriter来读写数据。注意,在读取和写入数据时,这些操作都是阻塞的。

这个例子展示了BIO的基本工作原理:读写操作受到操作系统的控制,并且在操作完成之前,执行这些操作的线程会被阻塞。在高并发的场景下,这种模型可能会导致资源利用率低下,因为每个连接都需要一个线程来处理。

八、NIO实现socket通信

使用Selector来实现非阻塞式I/O操作,我们创建一个简单的非阻塞式服务器,它能够同时处理多个客户端连接。
在这里插入图片描述

服务端:

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;  
import java.util.Set;  public class NonBlockingServer {  public static void main(String[] args) throws IOException {  // 创建一个Selector  Selector selector = Selector.open();  // 打开一个ServerSocketChannel并设置为非阻塞模式  ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();  serverSocketChannel.configureBlocking(false);  // 绑定ServerSocketChannel到一个地址和端口  serverSocketChannel.bind(new InetSocketAddress(8080));  // 将ServerSocketChannel注册到Selector,关心ACCEPT事件  serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);  while (true) {  // 阻塞等待需要处理的事件  int readyChannels = selector.select();  if (readyChannels == 0) continue;  // 获取可用通道集合  Set<SelectionKey> selectedKeys = selector.selectedKeys();  Iterator<SelectionKey> keyIterator = selectedKeys.iterator();  // 遍历SelectionKey  while (keyIterator.hasNext()) {  SelectionKey key = keyIterator.next();  // 检查是否有新的连接,如果有,则接受该连接  if (key.isAcceptable()) {  ServerSocketChannel server = (ServerSocketChannel) key.channel();  SocketChannel client = server.accept();  client.configureBlocking(false);  client.register(selector, SelectionKey.OP_READ);  System.out.println("Accepted new connection from " + client);  }  // 检查是否有数据可读  else if (key.isReadable()) {  SocketChannel client = (SocketChannel) key.channel();  ByteBuffer buffer = ByteBuffer.allocate(1024);  int bytesRead = client.read(buffer);  if (bytesRead == -1) {  client.close();  } else {  buffer.flip();  while (buffer.hasRemaining()) {  System.out.print((char) buffer.get());  }  client.register(selector, SelectionKey.OP_WRITE);  }  }  // 检查是否有数据可写  else if (key.isWritable()) {  SocketChannel client = (SocketChannel) key.channel();  ByteBuffer buffer = ByteBuffer.allocate(1024);  buffer.put("Hello from server!".getBytes());  buffer.flip();  client.write(buffer);  client.close();  }  // 处理完SelectionKey后,需要从集合中删除  keyIterator.remove();  }  }  }  
}
  • 我们首先创建了一个Selector实例,它将用于监控多个通道的状态。
  • 然后,我们打开了一个ServerSocketChannel,将其设置为非阻塞模式,并绑定到指定的端口(在这个例子中是8080)。
  • 我们将ServerSocketChannel注册到Selector,并指定我们关心ACCEPT事件,这意味着我们想要知道何时有新的连接请求。
  • 进入一个无限循环,在循环中,我们调用selector.select()来阻塞等待直到至少有一个通道准备好进行I/O操作。
  • 一旦select()返回,我们获取Selector中已选择的键的集合,并遍历它们。
  • 对于每个键,我们检查它是否可接受(即是否有新的连接等待被接受)、是否可读(即是否有数据可以从通道中读取)或是否可写(即是否有数据可以写入通道)。
  • 根据键的状态,我们执行相应的操作,如接受新连接、读取数据或写入数据。
  • 在处理完一个键之后,我们必须从选定的键集合中删除它,否则下次选择操作时它仍会被包含在内。

客户端将连接到服务器,发送一条消息,并等待接收服务器的响应

import java.io.IOException;  
import java.net.InetSocketAddress;  
import java.nio.ByteBuffer;  
import java.nio.channels.SocketChannel;  public class NonBlockingClient {  public static void main(String[] args) throws IOException {  // 打开一个SocketChannel并连接到服务器  SocketChannel socketChannel = SocketChannel.open();  socketChannel.configureBlocking(false);  socketChannel.connect(new InetSocketAddress("localhost", 8080));  // 完成连接过程  while (!socketChannel.finishConnect()) {  // 非阻塞模式下,可能需要多次调用finishConnect()来完成连接  System.out.println("Connecting to server...");  }  System.out.println("Connected to server");  // 准备要发送的数据  String message = "Hello from client!";  ByteBuffer writeBuffer = ByteBuffer.wrap(message.getBytes());  // 发送数据到服务器  while (writeBuffer.hasRemaining()) {  socketChannel.write(writeBuffer);  }  // 准备读取服务器的响应  ByteBuffer readBuffer = ByteBuffer.allocate(1024);  // 读取服务器的响应  while (true) {  int bytesRead = socketChannel.read(readBuffer);  if (bytesRead == -1) {  break; // 服务器已关闭连接  }  if (bytesRead > 0) {  readBuffer.flip();  while (readBuffer.hasRemaining()) {  System.out.print((char) readBuffer.get());  }  readBuffer.clear();  }  }  // 关闭SocketChannel  socketChannel.close();  }  
}
  • 我们首先创建一个SocketChannel实例,并设置其为非阻塞模式。
  • 使用connect()方法异步地连接到服务器。在非阻塞模式下,connect()方法可能立即返回,而连接过程可能尚未完成。因此,我们需要检查连接状态并可能需要多次调用finishConnect()来确保连接已经完成。
  • 一旦连接建立,我们创建一个包含要发送的消息的ByteBuffer,并使用SocketChannel的write()方法发送数据。注意,在非阻塞模式下,write()方法可能不会发送所有的数据,因此我们需要在循环中调用它,直到所有数据都被发送。
  • 接着,我们准备一个空的ByteBuffer来接收服务器的响应,并在一个循环中调用read()方法来读取数据。同样地,由于我们处于非阻塞模式,read()方法可能立即返回0(如果没有数据可读),或者返回实际读取的字节数。当read()返回-1时,表示服务器已经关闭了连接。
  • 我们使用flip()方法来准备从ByteBuffer中读取数据,并在读取完数据后使用clear()方法来清空缓冲区,以便下次读取。
  • 最后,我们关闭SocketChannel来释放资源。

九、总结

Java BIO和NIO是两种不同的I/O模型,它们在设计、工作原理和使用上有显著的区别。BIO是同步阻塞的I/O模型,它简单直接但性能有限;而NIO是同步非阻塞的I/O模型,它引入了多路复用器和缓冲区的概念,提高了系统的吞吐量和性能。在选择使用哪种模型时,需要根据具体的应用场景和需求进行权衡。如果并发连接数较少且对性能要求不高,可以选择使用BIO;如果并发连接数较多且对性能要求较高,可以选择使用NIO。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[C++]类和对象(中)

一:类的六个默认成员函数 如果一个类中什么成员都没有&#xff0c;简称为空类。空类中并不是什么都没有&#xff0c;任何类在什么都不写时&#xff0c;编译器会自动生成以下6个默认成员函数。默认成员函数&#xff1a;用户没有显式实现&#xff0c;编译器会生成的成员函数称为…

使用Python的Turtle模块简单绘制烟花效果

import turtle import random# 初始化屏幕 screen turtle.Screen() screen.bgcolor("black") screen.title("烟花模拟")# 创建一个Turtle来绘制烟花 firework turtle.Turtle() firework.hideturtle() firework.speed(0) # 设置绘图速度为最快# 绘制烟花…

GEDepth:Ground Embedding for Monocular Depth Estimation

参考代码&#xff1a;gedepth 出发点与动机 相机的外参告诉了相机在世界坐标系下的位置信息&#xff0c;那么可以用这个外参构建一个地面基础深度作为先验&#xff0c;后续只需要在这个地面基础深度先验基础上添加offset就可以得到结果深度&#xff0c;这样可以极大简化深度估…

springboot与springcloud之间的版本对应关系

https://start.spring.io/actuator/info 当然&#xff0c;你可以直接在&#xff1a; https://spring.io/projects/spring-cloud 上看文档查询&#xff0c; 不过&#xff0c;最后应该是调到这里的&#xff1a; https://github.com/spring-cloud/spring-cloud-release/wiki/Suppo…

C++:输入流/输出流

C流类库简介 C为了克服C语言中的scanf和printf存在的缺点。&#xff0c;使用cin/cout控制输入/输出。 cin&#xff1a;表示标准输入的istream类对象&#xff0c;cin从终端读入数据。cout&#xff1a;表示标准输出的ostream类对象&#xff0c;cout向终端写数据。cerr&#xff…

stable diffusion微调总结

stable diffusion微调总结 stable diffusion模型类别&#xff1a;SDSD2SDXLSDXL LCM&#xff08;潜在一致性模型&#xff09;SDXL DistilledSDXL Turbo 安装accelerate通过pip安装配置 accelerate config查看配置 安装diffusers数据处理BLIP模型优化 微调方法Dreambooth微调准备…

静态代理IP是如何助力跨境电商运营的?

&#x1f935;‍♂️ 个人主页&#xff1a;艾派森的个人主页 ✍&#x1f3fb;作者简介&#xff1a;Python学习者 &#x1f40b; 希望大家多多支持&#xff0c;我们一起进步&#xff01;&#x1f604; 如果文章对你有帮助的话&#xff0c; 欢迎评论 &#x1f4ac;点赞&#x1f4…

微信小程序 安卓/IOS兼容问题

一、背景 在开发微信小程序时&#xff0c;不同的手机型号会出现兼容问题&#xff0c;特此记录一下 二、安卓/IOS兼容问题总结 2.1、new Date()时间转换格式时&#xff0c;IOS不兼容 问题&#xff1a;在安卓中时间格式2024-1-31 10:10:10&#xff0c;但是在iOS中是不支持 &q…

jQuery前段开发--星级评价和图形跟随指针移动

一、实验原理&#xff1a; 当鼠标移入某个星星&#xff0c;前面的星星都会被点亮&#xff1b;当鼠标移出&#xff0c;星星将会变暗&#xff0c;单击某个星星后&#xff0c;即可完成评论&#xff0c;此时鼠标移出后&#xff0c;被单击星星前面的星星都会被点亮&#xff0c;后面…

幻兽帕鲁社区服务器搭建架设开服教程(LINUX)

幻兽帕鲁社区服务器搭建架设开服教程&#xff08;LINUX&#xff09; 大家好我是艾西&#xff0c;上一期我给大家分享了windows系统版本的幻兽帕鲁服务器搭建教程。因为幻兽帕鲁这游戏对于服务器的配置有一定的要求很多小伙伴就思考用linux系统搭建的话占用会不会小一点&#x…

华为云CodeArts Snap荣获信通院优秀大模型案例及两项荣誉证书

2024年1月25日&#xff0c;中国人工智能产业发展联盟智能化软件工程工作组&#xff08;AI for Software Engineering&#xff0c;下文简称AI4SE&#xff09;在京召开首届“AI4SE创新巡航”活动。在活动上&#xff0c;华为云大模型辅助系统测试代码生成荣获“2023AI4SE银弹优秀案…

代码随想录算法训练营第二十四天| 77. 组合。

77. 组合 题目链接&#xff1a;组合 题目描述&#xff1a; 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 解题思路&#xff1a; 本题是经典的回溯法解决的组合问题&#xff0c;回溯问题搞清楚纵向递归横向遍历即…

混乱字母排序——欧拉路数论

题目描述 小明接到一个神秘的任务&#xff1a;对于给定的 n 个没有顺序的字母对&#xff08;无序代表这两个字母可以前后顺序颠倒&#xff0c;区分大小写&#xff09;。请构造一个有 (n1) 个字母的混乱字符串使得每个字母对都在这个字符串中出现。 输入输出格式 输入格式 第…

KVM虚拟机MAC地址冲突,引发服务器对xshell说:Go away!

转载说明&#xff1a;如果您喜欢这篇文章并打算转载它&#xff0c;请私信作者取得授权。感谢您喜爱本文&#xff0c;请文明转载&#xff0c;谢谢。 开场白 最近在机房的服务器上装kvm虚拟主机。 不经意间&#xff0c;上演了一场由MAC地址异常而引发的服务器与xshell之间的血案…

宠物商业数据分析

一、宠物热销品类分布 欧睿国际更有一份数据表明&#xff0c;宠物食品在所有“它经济”中占比是最大&#xff0c;仅仅是猫狗食品就达到了59.1%&#xff0c;增速也远高于其他宠物用品。 2018年&#xff0c;中国就已经有超7700万独居成年人口&#xff0c;国内养宠主力军中90后占…

c++阶梯之auto关键字与范围for

auto关键字&#xff08;c11&#xff09; 1. auto关键字的诞生背景 随着程序的逐渐复杂&#xff0c;程序代码中用到的类型也越来越复杂。譬如&#xff1a; 类型难以拼写&#xff1b;含义不明确容易出错。 比如下面一段代码&#xff1a; #include <string> #include &…

nginx无法启动,win10占用80端口 (注册表方式解决)

参考&#xff1a;https://blog.csdn.net/qq_39523111/article/details/128853509 改为4 重启后 不再占用 pid 不是4了 已经变为nginx了 改为0 没起作用 发现 80端口还是被 4占用 可以 把 服务中的 SQL Server Reporting Services关掉

2024年美赛B题思路分析 - 搜索潜水器

# 1 赛题 问题B&#xff1a;搜索潜水器 总部位于希腊的小型海上巡航潜艇&#xff08;MCMS&#xff09;公司&#xff0c;制造能够将人类运送到海洋最深处的潜水器。潜水器被移动到该位置&#xff0c;并不受主船的束缚。MCMS现在希望用他们的潜水器带游客在爱奥尼亚海底探险&…

【疑问】为什么声明和定义要分离

前言 我们在学习的时候接触过一个话&#xff1a;编写自定义函数的时候 要做到声明和定义分离 那么为什么呢 今天就来简单的了解一下 疑问&#xff1a;错误的发生 下面给出两个源文件和一个头文件以及报错信息 text.cc文件 #include"head.h"int main() {int a 1…

Pytroch 自写训练模板适合入门版 包含十五种经典的自己复现的一维模型 1D CNN

训练模板 在毕业之前&#xff0c;决定整理一下手头的代码&#xff0c;自己做1D-CNN这吗久&#xff0c;打算开源一下自己使用的1D-CNN的代码&#xff0c;包括用随机数生成一个模拟的数据集&#xff0c;到自己写的一个比较好的适合入门的基础训练模板&#xff0c;以及自己复现的…