BIO、NIO、AIO之间有什么区别

文章目录

  • BIO
    • 优缺点
    • 示例代码
  • NIO
    • 优缺点
    • 示例代码
  • AIO
    • 优缺点
    • 示例代码
  • 总结

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。

BIO、NIO和AIO是Java编程语言中用于处理输入输出(IO)操作的三种不同的机制,它们分别代表同步阻塞I/O,同步非阻塞I/O和异步非阻塞I/O。

BIO

BIO(Blocking IO) 是最传统的IO模型,也称为同步阻塞IO。它实现的是同步阻塞模型,即服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理。如果这个连接不做任何事情会造成不必要的线程开销,并且线程在进行IO操作期间是被阻塞的,无法进行其他任务。在高并发环境下,BIO的性能较差,因为它需要为每个连接创建一个线程,而且线程切换开销较大,不过可以通过线程池机制改善。BIO适合一些简单的、低频的、短连接的通信场景,例如HTTP请求。

BIO模型

优缺点

优点:

  1. 简单易用: BIO模型的编程方式相对简单,易于理解和使用。
  2. 可靠性高: 由于阻塞特性,IO操作的结果是可靠的。

缺点:

  1. 阻塞等待: 当一个IO操作被阻塞时,线程会一直等待,无法执行其他任务,导致资源浪费。
  2. 并发能力有限: 每个连接都需要一个独立的线程,当连接数增加时,线程数量也会增加,造成资源消耗和性能下降。
  3. 由于I/O操作是同步的,客户端的连接需要等待服务器响应,会降低系统的整体性能。

示例代码

服务端代码:

import java.io.*;
import java.net.*;public class BIOServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = null;Socket clientSocket = null;try {//创建服务端serverSocket = new ServerSocket(8888);System.out.println("服务端已启动,等待客户端连接...");while (true){// 监听客户端请求,接收不到请求会一直等待clientSocket = serverSocket.accept();int port = clientSocket.getPort();InetAddress inetAddress = clientSocket.getInetAddress();System.out.println("客户端 "+inetAddress+":"+port+" 连接成功!");//处理客户端消息new Thread(new ServerThread(clientSocket)).start();}} catch (IOException e) {System.out.println("客户端连接失败:" + e.getMessage());} finally {try {if (clientSocket != null) {clientSocket.close();}if (serverSocket != null) {serverSocket.close();}} catch (IOException e) {System.out.println("关闭资源失败:" + e.getMessage());}}}
}/*** 服务端线程处理类*/
class ServerThread  implements Runnable{private Socket clientSocket;public ServerThread(Socket clientSocket) {this.clientSocket = clientSocket;}@Overridepublic void run() {//获取客户端输入流以便接收客户端数据try {BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));//获取客户端输出流以便向客户端发送数据PrintWriter out = new PrintWriter(clientSocket.getOutputStream());int port = clientSocket.getPort();InetAddress inetAddress = clientSocket.getInetAddress();String address = inetAddress+":"+port;String inputLine;while ((inputLine = in.readLine()) != null) {//接收客户端消息System.out.println("客户端"+address+"发来消息:" + inputLine);//给客户端发送消息out.println("服务端已接收到消息并回复:"+inputLine);out.flush();}} catch (IOException e) {e.printStackTrace();}}
}

客户端代码:

public class BIOClient {public static void main(String[] args) throws IOException {Socket clientSocket = null;BufferedReader in = null;PrintWriter out = null;try {//绑定服务端ip和端口号clientSocket = new Socket("localhost", 8888);System.out.println("连接服务端成功!");//获取输入流,接收服务端消息in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));//获取输出流,给服务端发送消息out = new PrintWriter(clientSocket.getOutputStream(), true);Scanner scanner = new Scanner(System.in);while (true){System.out.print("给服务端发送消息:");String msg = scanner.nextLine();out.println(msg);String response;if ((response = in.readLine()) != null) {//接收服务端响应System.out.println("服务端响应:" + response);}}} catch (IOException e) {System.out.println("连接服务端失败:" + e.getMessage());} finally {try {if (in != null) {in.close();}if (out != null) {out.close();}if (clientSocket != null) {clientSocket.close();}} catch (IOException e) {System.out.println("关闭资源失败:" + e.getMessage());}}}
}

运行结果:

服务端

客户端1

客户端2

上述代码只是简单演示了如何使用BIO模型一个服务端接收并处理多个客户端请求情况。在这里创建了3个类,分别为服务端 BIOServer、多线程客户端处理类ServerThread和 客户端BIOClient,接着分别启动服务端BIOServer和两个客户端BIOClient,并在客户端中接收键盘输入的字符串发送给服务端,最后服务端把接收到的数据再返回给客户端。

由于BIO的特性,所以在服务端中需要为每个连接创建一个线程,也可以通过线程池进行优化,这里只是简单演示不做过多设计。

NIO

NIO是Java 1.4引入的新IO模型,也称为同步非阻塞IO,它提供了一种基于事件驱动的方式来处理I/O操作。

相比于传统的BIO模型,NIO采用了Channel、Buffer和Selector等组件,线程可以对某个IO事件进行监听,并继续执行其他任务,不需要阻塞等待。当IO事件就绪时,线程会得到通知,然后可以进行相应的操作,实现了非阻塞式的高伸缩性网络通信。在NIO模型中,数据总是从Channel读入Buffer,或者从Buffer写入Channel,这种模式提高了IO效率,并且可以充分利用系统资源。

NIO主要有三部分组成:选择器(Selector)缓冲区(Buffer)通道(Channel)Channel是一个可以进行数据读写的对象,所有的数据都通过Buffer来处理,这种方式避免了直接将字节写入通道中,而是将数据写入包含一个或者多个字节的缓冲区。在多线程模式下,一个线程可以处理多个请求,这是通过将客户端的连接请求注册到多路复用器上,然后由多路复用器轮询到连接有I/O请求时进行处理。

对于NIO,如果从特性来看,它是非阻塞式IO,N是Non-Blocking的意思;如果从技术角度,NIO对于BIO来说是一个新技术,N的意思是New的意思。所以NIO也常常被称作Non-Blocking I/ONew I/O

NIO适用于连接数目多且连接比较短(轻操作)的架构,例如聊天服务器、弹幕系统、服务器间通讯等。它通过引入非阻塞通道的概念,提高了系统的伸缩性和并发性能。同时,NIO的使用也简化了程序编写,提高了开发效率。

NIO模型

优缺点

优点:

  1. 高并发性: 使用选择器(Selector)和通道(Channel)的NIO模型可以在单个线程上处理多个连接,提供更高的并发性能。
  2. 节省资源: 相对于BIO,NIO需要更少的线程来处理相同数量的连接,节省了系统资源。
  3. 灵活性: NIO提供了多种类型的ChannelBuffer,可以根据需要选择适合的类型。NIO允许开发人员自定义协议、编解码器等组件,从而提高系统的灵活性和可扩展性。
  4. 高性能: NIO采用了基于通道和缓冲区的方式来读写数据,这种方式比传统的流模式更高效。可以减少数据拷贝次数,提高数据处理效率。
  5. 内存管理:NIO允许用户手动管理缓冲区的内存分配和回收,避免了传统I/O模型中的内存泄漏问题。

缺点:

  1. 编程复杂: 相对于BIO,NIO的编程方式更加复杂,需要理解选择器和缓冲区等概念,也需要考虑多线程处理和同步问题。
  2. 可靠性较低: NIO模型中,一个连接的读写操作是非阻塞的,无法保证IO操作的结果是可靠的,可能会出现部分读写或者错误的数据。

NIO适合一些复杂的、高频的、长连接的通信场景,例如聊天室、网络游戏等。

示例代码

在看代码之前先了解NIO中3个非常重要的组件,选择器(Selector)缓冲区(Buffer)通道(Channel)

  1. 通道(Channel):Channel是NIO中用于数据读写的双向通道,可以从通道中读取数据,也可以将数据写入通道。与传统的IO不同,Channel是双向的,可以同时进行读写操作,而传统的IO只能通过InputStreamOutputStream进行单向读写。Java NIO中常见的Channel有:FileChannel(文件读写)、DatagramChannel(UDP协议)、SocketChannel(TCP协议)和ServerSocketChannel(监听TCP连接请求)等。

  2. 缓冲区(Buffer): Buffer是NIO中用于存储数据的缓冲区,可以理解为一个容器,可以从中读取数据,也可以将数据写入其中。Buffer具有一组指针来跟踪当前位置、限制和容量等属性。Java NIO中提供了多种类型的Buffer,例如ByteBufferCharBufferShortBufferIntBuffer等。每种类型的Buffer都有自己特定的读写方法,可以使用get()put()等方法来读写缓冲区中的数据。

  3. 选择器(Selector): Selector是NIO中用于监控多个Channel的选择器,可以实现单线程管理多个Channel。Selector可以检测多个Channel是否有事件发生,包括连接、接收、读取和写入等事件,并根据不同的事件类型进行相应处理。Selector可以有效地减少单线程管理多个Channel时的资源占用,提高程序的运行效率。

NIO的操作流程如下:

  1. 打开通道并设置为非阻塞模式。
  2. 将通道注册到选择器上,并指定感兴趣的事件类型(如连接打开、可读等)。
  3. 线程通过调用选择器的select()方法等待事件发生。
  4. 当有一个或多个事件发生时,线程可以从选择器中获取已经准备好的通道,并进行相应的IO操作。
  5. IO操作完成后,关闭通道和选择器。

下面通过两段代码展示一下NIO的操作流程和使用方式。

服务端代码:

public class NIOServer {public static void main(String[] args) throws IOException {Selector selector = Selector.open();// 创建一个ServerSocketChannel并绑定到指定的端口ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.bind(new InetSocketAddress(9999));// 设置为非阻塞模式serverSocketChannel.configureBlocking(false);// 将ServerSocketChannel注册到Selector上,并监听OP_ACCEPT事件serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务器已启动,等待客户端连接...");while (true) {// 阻塞,等待事件发生selector.select();Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if (key.isAcceptable()) {     // 处理连接请求事件SocketChannel client = serverSocketChannel.accept();client.configureBlocking(false);//监听OP_ACCEPT事件client.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel client = (SocketChannel) key.channel();client.getRemoteAddress();//分配缓存区容量ByteBuffer buffer = ByteBuffer.allocate(1024);client.read(buffer);String output = new String(buffer.array()).trim();Socket socket = client.socket();InetAddress inetAddress = socket.getInetAddress();int port = socket.getPort();String clientInfo = inetAddress+":"+port;String message = String.format("来自客户端 %s , 消息:%s", clientInfo , output);System.out.println(message);System.out.print("回复消息: ");writeMessage(selector, client, buffer);}keyIterator.remove();}}}private static void writeMessage(Selector selector, SocketChannel client, ByteBuffer buffer) throws IOException {Scanner scanner = new Scanner(System.in);String message = scanner.nextLine();buffer.clear();buffer.put(message.getBytes());//从写模式切换到读模式buffer.flip();while (buffer.hasRemaining()) {client.write(buffer);}//  重新监听OP_ACCEPT事件client.register(selector, SelectionKey.OP_READ);}
}

客户端代码:

/*** @author 公众号:索码理(suncodernote)*/
public class NIOClient {public static void main(String[] args) throws IOException {Selector selector = Selector.open();SocketChannel socketChannel = SocketChannel.open();socketChannel.configureBlocking(false);socketChannel.connect(new InetSocketAddress("localhost", 9999));socketChannel.register(selector, SelectionKey.OP_CONNECT);while (true) {selector.select();Set<SelectionKey> selectedKeys = selector.selectedKeys();Iterator<SelectionKey> keyIterator = selectedKeys.iterator();while (keyIterator.hasNext()) {SelectionKey key = keyIterator.next();if (key.isConnectable()) {SocketChannel client = (SocketChannel) key.channel();if (client.isConnectionPending()) {client.finishConnect();}System.out.print("Enter message to server: ");Scanner scanner = new Scanner(System.in);String message = scanner.nextLine();ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());client.write(buffer);client.register(selector, SelectionKey.OP_READ);} else if (key.isReadable()) {SocketChannel client = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(1024);client.read(buffer);String output = new String(buffer.array()).trim();System.out.println("来自客户端的消息: " + output);System.out.print("输入消息: ");// 和服务端代码一样writeMessage(selector, client, buffer);}keyIterator.remove();}}}
}

运行结果:

server端

猎鹰

苍狼

上面代码新建了两个类:服务端(NIOServer)和客户端(NIOClient), 通过上面代码和运行结果可以发现,在服务端和客户端进行通信时,我们并没有新建线程类进行通信,这也是NIO和BIO最大的区别之一。

需要注意的是,虽然NIO提高了系统的并发性能和伸缩性,但也带来了更高的编程复杂度和更难的调试问题。因此,在使用Java NIO时,需要仔细考虑其适用场景和编程模型。

AIO

Java AIO(Asynchronous I/O)是Java提供的异步非阻塞IO编程模型,从Java 7版本开始支持,AIO又称NIO 2.0。

相比于NIO模型,AIO模型更进一步地实现了异步非阻塞IO,提高了系统的并发性能和伸缩性。在NIO模型中,虽然可以通过多路复用器处理多个连接请求,但仍需要在每个连接上进行读写操作,这仍然存在一定的阻塞。而在AIO模型中,所有的IO操作都是异步的,不会阻塞任何线程,可以更好地利用系统资源。

AIO模型有以下特性:

  1. 异步能力:AIO模型的最大特性是异步能力,对于socket和I/O操作都有效。读写操作都是异步的,完成后会自动调用回调函数。
  2. 回调函数:在AIO模型中,当一个异步操作完成后,会通知相关线程进行后续处理,这种处理方式称为“回调”。回调函数可以由开发者自行定义,用于处理异步操作的结果。
  3. 非阻塞:AIO模型实现了完全的异步非阻塞IO,不会阻塞任何线程,可以更好地利用系统资源。
  4. 高性能:由于AIO模型的异步能力和非阻塞特性,它可以更好地处理高并发、高伸缩性的网络通信场景,进一步提高系统的性能和效率。
  5. 操作系统支持:AIO模型需要操作系统的支持,因此在不同的操作系统上可能会有不同的表现。在Linux内核2.6版本之后增加了对真正异步IO的实现。

优缺点

优点:

  1. 非阻塞:AIO的主要优点是它是非阻塞的。这意味着在读写操作进行时,程序可以继续执行其他任务。这对于需要处理大量并发连接的高性能服务器来说是非常有用的。

  2. 高效:由于AIO可以处理大量并发连接,因此它通常比同步I/O(例如Java的传统I/O和NIO)更高效。

  3. 简化编程模型:AIO使用了回调函数,这使得编程模型相对简单。当一个操作完成时,会自动调用回调函数,无需程序员手动检查和等待操作的完成。

缺点:

  1. 复杂性:虽然AIO的编程模型相对简单,但是由于其非阻塞的特性,编程复杂性可能会增加。例如,需要处理操作完成的通知,以及可能的并发问题。

  2. 资源消耗:AIO可能会消耗更多的系统资源。因为每个操作都需要创建一个回调函数,如果并发连接数非常大,可能会消耗大量的系统资源。

  3. 可移植性:AIO在某些平台上可能不可用或者性能不佳。因此,如果需要跨平台的可移植性,可能需要考虑使用其他I/O模型。

AIO适合一些极端的、超高频的、超长连接的通信场景,例如云计算、大数据等。

需要注意的是,目前AIO模型还没有广泛应用,Netty等网络框架仍然是基于NIO模型。

示例代码

服务端:

/*** @author 公众号:索码理(suncodernote)*/
public class AIOServer {public static void main(String[] args) throws Exception {// 创建一个新的异步服务器套接字通道,绑定到指定的端口上final AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(5000));System.out.println("服务端启动成,等待客户端连接。");// 开始接受新的客户端连接serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {@Overridepublic void completed(AsynchronousSocketChannel clientChannel, Void att) {// 当一个新的连接完成时,再次接受新的客户端连接serverChannel.accept(null, this);// 创建一个新的缓冲区来读取数据ByteBuffer buffer = ByteBuffer.allocate(1024);try {InetSocketAddress clientAddress = (InetSocketAddress) clientChannel.getRemoteAddress();InetAddress clientIP = clientAddress.getAddress();int clientPort = clientAddress.getPort();System.out.println("客户端 "+ clientIP + ":" + clientPort + " 连接成功。");} catch (IOException e) {e.printStackTrace();}// 从异步套接字通道中读取数据clientChannel.read(buffer, buffer, new ReadCompletionHandler(clientChannel));}@Overridepublic void failed(Throwable exc, Void attachment) {System.out.println("Failed to accept a connection");}});// 保持服务器开启Thread.sleep(Integer.MAX_VALUE);}
}

读处理程序:

/*** @author 公众号:索码理(suncodernote)*/
public class ReadCompletionHandler implements CompletionHandler<Integer, ByteBuffer> {private AsynchronousSocketChannel channel;public ReadCompletionHandler(AsynchronousSocketChannel channel) {this.channel = channel;}@Overridepublic void completed(Integer result, ByteBuffer attachment) {// 当读取完成时,反转缓冲区并打印出来attachment.flip();byte[] bytes = new byte[attachment.remaining()];attachment.get(bytes);System.out.println("收到的消息: " + new String(bytes , StandardCharsets.UTF_8));attachment.clear();// 从键盘读取输入Scanner scanner = new Scanner(System.in);System.out.print("输入消息: ");String message = scanner.nextLine();System.out.println();// 写入数据到异步套接字通道channel.write(ByteBuffer.wrap(message.getBytes()));channel.read(attachment , attachment , new ReadCompletionHandler(channel));}@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {System.out.println("Failed to read message");}
}

客户端:

/*** @author 公众号:索码理(suncodernote)*/
public class AIOClient {public static void main(String[] args) throws Exception {// 创建一个新的异步套接字通道AsynchronousSocketChannel clientChannel = AsynchronousSocketChannel.open();// 连接到服务器clientChannel.connect(new InetSocketAddress("localhost", 5000), null, new CompletionHandler<Void, Void>() {@Overridepublic void completed(Void result, Void attachment) {System.out.println("连接到服务端成功。");}@Overridepublic void failed(Throwable exc, Void attachment) {System.out.println("Failed to connect server");}});// 从键盘读取输入Scanner scanner = new Scanner(System.in);System.out.print("发送消息: ");String message = scanner.nextLine();// 写入数据到异步套接字通道clientChannel.write(ByteBuffer.wrap(message.getBytes()), null, new CompletionHandler<Integer, Void>() {@Overridepublic void completed(Integer result, Void attachment) {ByteBuffer buffer = ByteBuffer.allocate(1024);clientChannel.read(buffer, buffer, new ReadCompletionHandler(clientChannel));}@Overridepublic void failed(Throwable exc, Void attachment) {System.out.println("Failed to write message");}});// 保持客户端开启Thread.sleep(Integer.MAX_VALUE);}
}

测试结果:

服务端界面:

客户端1:

客户端2:

客户端3:

上述示例代码中,通过一个服务端(AIOServer)和3个客户端(AIOClient)的通信,简单演示了AIO的使用。可以发现,AIO和NIO的使用方式基本一致,数据都是从Channel读入Buffer,或者从Buffer写入Channel中,不同的是AIO是实现了异步非阻塞。

总结

Java中的BIO、NIO和AIO都是处理输入/输出(I/O)操作的模型,但它们在处理方式和效率上有所不同。

  1. BIO(Blocking I/O):BIO是最传统的I/O模型,它的操作都是阻塞的。这意味着,当一个线程发起一个I/O操作后,必须等待操作完成才能进行其他任务。因此,BIO在处理大量并发连接时效率较低,但其编程模型简单。

  2. NIO(Non-blocking I/O):NIO是非阻塞的I/O模型,它允许线程在等待I/O操作完成时进行其他任务。NIO引入了Channel和Buffer的概念,以及Selector用于多路复用。NIO适合处理大量并发连接,但其编程模型相对复杂。

  3. AIO(Asynchronous I/O):AIO是真正的异步I/O模型,应用程序无需等待I/O操作的完成,当操作完成时,操作系统会通知应用程序。AIO使用回调函数或Future对象来获取操作结果,适合处理大量并发连接,其编程模型相对简单。

总之,BIO、NIO和AIO各有优缺点,适用的场景也不同。BIO适合连接数目较少且固定的架构,NIO适合连接数目多,但是并发读写操作相对较少的场景,AIO则适合连接数目多,且并发读写操作也多的场景。在选择使用哪种I/O模型时,需要根据具体的应用场景和需求进行权衡。

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

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

相关文章

MYSQL字符串函数详解和实战(字符串函数大全,内含示例)

MySQL提供了许多字符串函数&#xff0c;用于处理和操作字符串数据。以下是一些常用的MYSQL字符串函数。 建议收藏以备后续用到查阅参考。 目录 一、CONCAT 拼接字符串 二、CONCAT_WS 拼接字符串 三、SUBSTR 取子字符串 四、SUBSTRING 取子字符串 五、SUBSTRING_INDEX 取子…

《红蓝攻防对抗实战》十二.内网穿透之利用ICMP协议进行隧道穿透

内网穿透之利用ICMP协议进行隧道穿透 一.前言二.前文推荐三.利用ICMP协议进行隧道穿透1.ICMPsh获取反弹shell2.PingTunnel 搭建隧道 四.本篇总结 一.前言 本文介绍了利用ICMP协议进行隧道穿透的方法。ICMP协议不需要开放端口&#xff0c;可以将TCP/UDP数据封装到ICMP的Ping数据…

Mysql数据库 14.SQL语言 视图

一、视图的概念 视图&#xff1a;就是由数据库中一张或多张表根据特定的条件查询出的数据狗造成的虚拟表 二、视图的作用 安全性&#xff0c;简单性 三、视图的语法 语法 create view 视图表 as select_statement; 代码实现 #创建视图 将查询结果创建称为视图&#x…

Flutter开发中的一些Tips(四)

最近接手了一个flutter项目&#xff0c;整体感觉代码质量不高&#xff0c;感觉有些是初学者容易犯的问题。几年前写的前三篇&#xff0c;我是站在我自己开发遇到问题的角度&#xff0c;这篇是站在别人遇到问题的角度&#xff0c;算是一种补充。下面我整理一下遇到的小问题&…

中国专利转让数据集(1985-2021年)

专利转让数据追踪和记录专利从一个实体转移到另一个实体的过程。这些数据不仅包括参与转让的申请人和受让人的身份信息&#xff0c;如名字和地址&#xff0c;还涵盖了转让的具体法律细节&#xff0c;包括转让执行日、转让次数、法律状态变更&#xff0c;以及转让登记的相关信息…

在Spring Boot中使用MyBatis访问数据库

MyBatis&#xff0c;这个对各位使用Java开发的开发者来说还是蛮重要的&#xff0c;我相信诸位在企业开发项目的时候&#xff0c;大多数采用的是Mybatis。使用MyBatis帮助我们解决各种问题&#xff0c;实际上这篇文章&#xff0c;基本上默认为可以跳过的一篇&#xff0c;但是为了…

Linux服务器从零开始训练 RT-DETR 改进项目 (Ultralytics) 教程,改进RTDETR算法(包括使用训练、验证、推理教程)

手把手从零开始训练 RT-DETR 改进项目 (Ultralytics版本) 教程,改进RTDETR算法 本文以Linux服务器为例:从零开始使用Linux训练 RT-DETR 算法项目 《芒果剑指 RT-DETR 目标检测算法 改进》 适用于芒果专栏改进RT-DETR算法 文章目录 百度 RT-DETR 算法介绍改进网络代码汇总第…

arcgis基础篇--实验

一、绘制带空洞的面要素 方法一&#xff1a;先绘制出一个面区域&#xff0c;然后在面上再绘制一个面区域代表面洞&#xff0c;两者位于同一个图层内&#xff0c;选中代表面洞的区域&#xff0c;选择【编辑器】-【裁剪】工具&#xff0c;将面裁剪出一个洞&#xff0c;随后删除代…

openinstall携手途虎养车,赋能汽车服务数字化

近日&#xff0c;openinstall与中国领先的一站式汽车服务平台途虎养车再次续约&#xff0c;双方将开启第三年合作。过去两年&#xff0c;途虎在建设线上线下一体化数字平台的过程中&#xff0c;深度结合openinstall传参归因与渠道统计技术&#xff0c;打造出了一套高效的渠道来…

GZ038 物联网应用开发赛题第4套

2023年全国职业院校技能大赛 高职组 物联网应用开发 任 务 书 &#xff08;第4套卷&#xff09; 工位号&#xff1a;______________ 第一部分 竞赛须知 一、竞赛要求 1、正确使用工具&#xff0c;操作安全规范&#xff1b; 2、竞赛过程中如有异议&#xff0c;可向现场考评…

Hadoop学习总结(使用Java API操作HDFS)

使用Java API操作HDFS&#xff0c;是在安装和配置Maven、IDEA中配置Maven成功情况下进行的&#xff0c;如果Maven安装和配置不完全将不能进行Java API操作HDFS。 由于Hadoop是使用Java语言编写的&#xff0c;因此可以使用Java API操作Hadoop文件系统。使用HDFS提供的Java API构…

C语言进阶

数组 在基础篇说过&#xff0c;数组实际上是构造类型之一&#xff0c;是连续存放的。 一维数组 定义 定义格式&#xff1a;[存储类型] 数据类型 数组名标识符[下标]; 下面分模块来介绍一下数组的定义部分的内容。 1、初始化和元素引用&#xff1a; 可以看到数组是连续存储…

Linux--gcc/g++

一、gcc/g是什么 gcc的全称是GNU Compiler Collection&#xff0c;它是一个能够编译多种语言的编译器。最开始gcc是作为C语言的编译器&#xff08;GNU C Compiler&#xff09;&#xff0c;现在除了c语言&#xff0c;还支持C、java、Pascal等语言。gcc支持多种硬件平台 二、gc…

数据结构 队列(C语言实现)

目录 1.队列的概念及结构2.队列的代码实现 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站。 1.队列的概念及结构 队列&#xff1a;只允许在…

Java Web——TomcatWeb服务器

目录 1. 服务器概述 1.1. 服务器硬件 1.2. 服务器软件 2. Web服务器 2.1. Tomcat服务器 2.2. 简单的Web服务器使用 1. 服务器概述 服务器指的是网络环境下为客户机提供某种服务的专用计算机&#xff0c;服务器安装有网络操作系统和各种服务器的应用系统服务器的具有高速…

【2011年数据结构真题】

41题 41题解答&#xff1a; &#xff08;1&#xff09;图 G 的邻接矩阵 A 如下所示&#xff1a; 由题意得&#xff0c;A为上三角矩阵&#xff0c;在上三角矩阵A[6][6]中&#xff0c;第1行至第5行主对角线上方的元素个数分别为5, 4, 3, 2, 1 用 “ 平移” 的思想&#xff0c;…

vmware workstation 与 device/credential guard 不兼容

VM虚拟机报错 vmware虚拟机启动时报错&#xff1a;vmware workstation 与 device/credential guard 不兼容&#xff1a; 系统是win10专业版&#xff0c;导致报错原因最终发现是安装了docker&#xff0c;docker自带下载虚拟机Hyper-V&#xff0c;而导致vmware workstation 与 …

FPGA高端项目:图像采集+GTX+UDP架构,高速接口以太网视频传输,提供2套工程源码加QT上位机源码和技术支持

目录 1、前言免责声明本项目特点 2、相关方案推荐我这里已有的 GT 高速接口解决方案我这里已有的以太网方案 3、设计思路框架设计框图视频源选择OV5640摄像头配置及采集动态彩条视频数据组包GTX 全网最细解读GTX 基本结构GTX 发送和接收处理流程GTX 的参考时钟GTX 发送接口GTX …

MSF图形化工具Viper快速安装

简介 Viper(炫彩蛇)是一款图形化内网渗透工具,将内网渗透过程中常用的战术及技术进行模块化及武器化. Viper(炫彩蛇)集成杀软绕过,内网隧道,文件管理,命令行等基础功能. Viper(炫彩蛇)当前已集成70个模块,覆盖初始访问/持久化/权限提升/防御绕过/凭证访问/信息收集/横向移动等…

Python的基础语句大全

以下是Python的基础语句大全&#xff1a; 变量定义语句&#xff1a; var_name var_value输出语句&#xff1a; print(var_name)输入语句&#xff1a; var_name input()条件语句&#xff1a; if condition:// do something if condition is True elif condition:// do somethi…