Java Socket 網絡編程實例(阻塞IO、非阻塞IO、多路復用Selector、AIO)

文章目錄

  • 1. 概述
  • 2. TCP 阻塞式IO 網絡編程實例
    • 2.1 TCP網絡編程服務端
    • 2.2 ByteBufferUtil
    • 2.3 客戶端代碼
    • 2.4 運行截圖
  • 3. TCP 非阻塞式IO 網絡編程實例
    • 3.1 服務端
    • 3.2 客戶端
    • 3.3 運行截圖
  • 4. 多路復用
    • 4.1 服務器端
    • 4.2 客戶端
    • 4.3 運行截圖
  • 5. AIO
    • 5.1 AIO 服務端
    • 5.2 客戶端
    • 5.3 運行截圖
  • 6. Channel / Buffer
    • 6.1 Channel
    • 6.2 ByteBuffer
  • 參考文獻

1. 概述

  • 網絡編程, 就是編寫程序, 使兩臺聯網的電腦可以交換數據,
  • 套接字是網絡數據傳輸用的軟件設備, 用來連接網絡的工具
  • 在 linux中 socket被認為是文件中的一種, 在網絡數據傳輸過程中, 使用文件I/O的相關函數
  • socket 幫助程序員封裝了網絡的底層細節,如:錯誤檢測、包大小、包分解、包重傳、網絡地址等,讓程序員將網絡連接看作可以讀/寫字節的流
  • 套接字常用網絡協議: TCP、UDP

之前還有一篇文章: Linux C++ Socket 套接字、select、poll、epoll 實例

套接字進行網絡連接流程, 如下圖:

服務器端:

  1. 創建服務器套接字 socket()
  2. 綁定端口 bind()
  3. 監聽端口 listen()
  4. 接受客戶端請求 accept()
  5. 讀取客戶端請求的數據 read()
  6. 返回客戶端要響應的數據 write()
  7. 關閉與客戶端的連接 close()
  8. 關閉服務器套接字 close()

客戶端:

  1. 創建客戶端套接字 socket()
  2. 連接服務端 connect()
  3. 請求服務端數據, 發送操作數和操作符到服務器 write()
  4. 從服務器讀取操作結果 read()
  5. 關閉客戶端套接字 close()

流程圖如下, 具體代碼示例可以看下面的 2. TCP 阻塞式IO 網絡編程實例在這里插入圖片描述

2. TCP 阻塞式IO 網絡編程實例

accept 和 read 都是阻塞的, 當 accept 到新連接, 或者 read 到數據程序才往下走

為了提高服務端處理能力, 一個客戶端連接一個線程處理

不能一個線程處理多個客戶端, 某個客戶端會阻塞這個線程處理其他客戶端

在這里插入圖片描述

2.1 TCP網絡編程服務端

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;public class BlockServer {public static void main(String[] args) throws IOException {// 0. ByteBufferByteBuffer buffer = ByteBuffer.allocate(16);// 1. 創建了服務器ServerSocketChannel ssc = ServerSocketChannel.open();// 2. 綁定監聽端口ssc.bind(new InetSocketAddress(8080));// 3. 連接集合List<SocketChannel> channels = new ArrayList<>();while (true) {// 4. accept 建立與客戶端連接, SocketChannel 用來與客戶端之間通信System.out.println("等待客戶端連接...");SocketChannel sc = ssc.accept(); // 阻塞方法,線程停止運行System.out.println("接收到客戶端連接: " + sc);channels.add(sc);for (SocketChannel channel : channels) {// 5. 接收客戶端發送的數據System.out.println("開始讀取客戶端中的數據:" + channel);channel.read(buffer); // 阻塞方法,線程停止運行buffer.flip();String request = ByteBufferUtil.read(buffer);System.out.println(request);buffer.clear();System.out.println("已經讀取完客戶端中的數據:" + channel);}}}
}

2.2 ByteBufferUtil

public class ByteBufferUtil {public static String read(ByteBuffer byteBuffer) throws CharacterCodingException {CharBuffer charBuffer = StandardCharsets.UTF_8.decode(byteBuffer);return charBuffer.toString();}public static ByteBuffer read(String string) throws CharacterCodingException {return StandardCharsets.UTF_8.encode(string);}public static void main(String[] args) throws CharacterCodingException {System.out.println(ByteBufferUtil.read(ByteBufferUtil.read("test")));}}

2.3 客戶端代碼

public class BlockClient {public static void main(String[] args) throws IOException {SocketChannel sc = SocketChannel.open();System.out.println("開始連接服務端...");sc.connect(new InetSocketAddress("localhost", 8080));String str = "test";System.out.println("連接服務端成功,寫入數據: " + str);sc.write(ByteBufferUtil.read(str));}
}

2.4 運行截圖

在這里插入圖片描述
在這里插入圖片描述

3. TCP 非阻塞式IO 網絡編程實例

不停的輪詢, 看看有沒有accept 到新連接, 沒有連接不阻塞等待, 繼續去看看已經建立的連接有沒有read到客戶端的新數據, read到新數據處理, read不到不處理

為了提高服務端處理能力, 可以一個客戶端連接一個線程處理, 線程不停的輪詢自己要處理的客戶端

也可以一個線程處理多個客戶端, 相較于上面的阻塞I/O模型, 非阻塞不至于某個客戶端阻塞這個線程處理其他客戶端

在這里插入圖片描述

3.1 服務端

ssc.configureBlocking(false); 設置為非阻塞模式

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;public class NonBlockServer {public static void main(String[] args) throws IOException, InterruptedException {// 0. ByteBufferByteBuffer buffer = ByteBuffer.allocate(16);// 1. 創建了服務器ServerSocketChannel ssc = ServerSocketChannel.open();ssc.configureBlocking(false); // 非阻塞模式// 2. 綁定監聽端口ssc.bind(new InetSocketAddress(8080));// 3. 連接集合List<SocketChannel> channels = new ArrayList<>();while (true) {// 4. accept 建立與客戶端連接, SocketChannel 用來與客戶端之間通信SocketChannel sc = ssc.accept(); // 非阻塞,線程還會繼續運行,如果沒有連接建立,但sc是nullif (sc != null) {System.out.println("接收到客戶端連接: " + sc);sc.configureBlocking(false); // 非阻塞模式channels.add(sc);}for (SocketChannel channel : channels) {System.out.println("開始讀取客戶端中的數據:" + channel);// 5. 接收客戶端發送的數據int read = channel.read(buffer);// 非阻塞,線程仍然會繼續運行,如果沒有讀到數據,read 返回 0if (read > 0) {buffer.flip();System.out.println((ByteBufferUtil.read(buffer)));buffer.clear();System.out.println("已經讀取完客戶端中的數據:" + channel);} else {TimeUnit.MILLISECONDS.sleep(100);}}}}
}

3.2 客戶端

客戶端同上

3.3 運行截圖

在這里插入圖片描述

在這里插入圖片描述

4. 多路復用

可以調用 select/poll/epoll , 阻塞在select/poll/epoll, select/poll/epoll 監聽多個客戶端連接事件或寫入的數據, 然后這些事件可再有多個線程分一分處理掉

在這里插入圖片描述

4.1 服務器端

打開選擇器并將其與通道注冊,監聽接受連接操作:

Selector selector = Selector.open();
channel.configureBlocking(false);
channel.register(selector, SelectionKey.OP_ACCEPT);

監聽選擇器上的事件,返回已就緒的通道數量:

int count = selector.select();

獲取所有事件(連接、讀取):

Set<SelectionKey> keys = selector.selectedKeys();
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;public class SelectorServer {public static void main(String[] args) {try (ServerSocketChannel channel = ServerSocketChannel.open()) {// 綁定端口并打印通道信息channel.bind(new InetSocketAddress(6666));System.out.println(channel);// 打開選擇器并將其與通道注冊,監聽接受連接操作Selector selector = Selector.open();channel.configureBlocking(false);channel.register(selector, SelectionKey.OP_ACCEPT);// 無限循環,等待選擇器上的事件while (true) {// 監聽選擇器上的事件,返回已就緒的通道數量int count = selector.select();System.out.println("select count: " + count);// 如果沒有就緒的通道,則繼續循環等待if (count <= 0) {continue;}// 獲取并迭代處理所有就緒的事件// 獲取所有事件Set<SelectionKey> keys = selector.selectedKeys();// 遍歷所有事件,逐一處理Iterator<SelectionKey> iter = keys.iterator();while (iter.hasNext()) {SelectionKey key = iter.next();// 處理接受連接事件// 判斷事件類型if (key.isAcceptable()) {ServerSocketChannel c = (ServerSocketChannel) key.channel();// 必須處理SocketChannel sc = c.accept();sc.configureBlocking(false);sc.register(selector, SelectionKey.OP_READ);System.out.println("連接已建立:" + sc);}// 處理讀取數據事件else if (key.isReadable()) {SocketChannel sc = (SocketChannel) key.channel();ByteBuffer buffer = ByteBuffer.allocate(128);int read = sc.read(buffer);if (read == -1) {// 如果讀取返回-1,表示連接已關閉key.cancel();sc.close();} else {// 否則,將緩沖區反轉并打印讀取的數據buffer.flip();System.out.println(new String(buffer.array(), StandardCharsets.UTF_8));}}// 事件處理完畢后,從迭代器中移除,避免重復處理// 處理完畢,必須將事件移除iter.remove();}}} catch (IOException e) {// 打印IO異常堆棧跟蹤e.printStackTrace();}}
}

4.2 客戶端

import netty.ByteBufferUtil;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;public class SelectorClient {public static void main(String[] args) throws IOException {// 創建Socket通道并連接到服務器SocketChannel sc = SocketChannel.open();sc.connect(new InetSocketAddress("localhost", 6666));// 初始化輸入和輸出ByteBufferByteBuffer inputBuffer = ByteBuffer.allocate(512);ByteBuffer serverOutput = ByteBuffer.allocate(512);// 循環接收用戶輸入并發送給服務器while (true) {// 使用Scanner獲取用戶輸入Scanner in = new Scanner(System.in);String input = in.nextLine();System.out.println("user input: " + input);// 清空輸入緩沖區,放入用戶輸入,然后反轉準備寫入inputBuffer.clear();inputBuffer.put(input.getBytes(StandardCharsets.UTF_8));inputBuffer.flip();// 將輸入數據寫入Socket通道sc.write(inputBuffer);System.out.println("send to server " + input);// 循環讀取服務器響應while (true) {// 清空服務器響應緩沖區,準備讀取數據serverOutput.clear();// 從Socket通道讀取數據sc.read(serverOutput);// 如果沒有讀取到數據,繼續嘗試讀取if (!serverOutput.hasRemaining()) {continue;}// 反轉緩沖區,讀取數據并打印serverOutput.flip();System.out.println("server response " + ByteBufferUtil.read(serverOutput));// 讀取完成后退出內層循環break;}}}
}

4.3 運行截圖

在這里插入圖片描述
在這里插入圖片描述

5. AIO

異步I/O模型

告訴內核啟動某個操作, 并且把數據copy到用戶緩沖區再通知我們

在這里插入圖片描述

5.1 AIO 服務端

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.nio.charset.Charset;/*** AIO服務器類,用于演示異步IO的服務器端實現。* 使用AsynchronousServerSocketChannel處理客戶端連接和數據傳輸。*/
public class AIOServer {/*** 程序入口,初始化并啟動AIO服務器。* 綁定服務器端口并等待客戶端連接。** @param args 命令行參數* @throws IOException 如果綁定端口失敗*/public static void main(String[] args) throws IOException {AsynchronousServerSocketChannel ssc = AsynchronousServerSocketChannel.open();ssc.bind(new InetSocketAddress(6666));ssc.accept(null, new AcceptHandler(ssc));while (true) ;}/*** 關閉客戶端通道的方法。* 用于處理讀取或寫入操作失敗時關閉通道。** @param sc 客戶端通道*/private static void closeChannel(AsynchronousSocketChannel sc) {try {System.out.printf("[%s] %s close\n", Thread.currentThread().getName(), sc.getRemoteAddress());sc.close();} catch (IOException e) {e.printStackTrace();}}/*** 讀取數據的完成處理器,實現讀取客戶端數據并響應的邏輯。*/private static class ReadHandler implements CompletionHandler<Integer, ByteBuffer> {private final AsynchronousSocketChannel sc;public ReadHandler(AsynchronousSocketChannel sc) {this.sc = sc;}/*** 當讀取操作完成時被調用。* 解析讀取的數據并寫回響應到客戶端。** @param result     讀取操作的結果* @param attachment 讀取操作的附加上下文*/@Overridepublic void completed(Integer result, ByteBuffer attachment) {try {if (result == -1) {return;}System.out.printf("[%s] %s read\n", Thread.currentThread().getName(), sc.getRemoteAddress());attachment.flip();String request = Charset.defaultCharset().decode(attachment).toString();System.out.println(request.toString());attachment.clear();attachment.put(("你好:" + request).getBytes());attachment.flip();sc.write(attachment);attachment.clear();// 讀取下一個讀時間sc.read(attachment, attachment, new ReadHandler(sc));} catch (IOException e) {e.printStackTrace();}}/*** 當讀取操作失敗時被調用。* 關閉客戶端通道并打印異常堆棧跟蹤。** @param exc        引發的異常* @param attachment 讀取操作的附加上下文*/@Overridepublic void failed(Throwable exc, ByteBuffer attachment) {closeChannel(sc);exc.printStackTrace();}}/*** 接受連接的完成處理器,用于處理客戶端的連接請求。*/private static class AcceptHandler implements CompletionHandler<AsynchronousSocketChannel, Object> {private final AsynchronousServerSocketChannel ssc;public AcceptHandler(AsynchronousServerSocketChannel ssc) {this.ssc = ssc;}/*** 當接受操作完成時被調用。* 設置讀取緩沖區并開始讀取客戶端發送的數據。** @param sc         接受到的客戶端通道* @param attachment 接受操作的附加上下文*/@Overridepublic void completed(AsynchronousSocketChannel sc, Object attachment) {try {System.out.printf("[%s] %s connected\n", Thread.currentThread().getName(), sc.getRemoteAddress());} catch (IOException e) {e.printStackTrace();}ByteBuffer buffer = ByteBuffer.allocate(1024);// 讀事件由 ReadHandler 處理System.out.println("開始讀");sc.read(buffer, buffer, new ReadHandler(sc));System.out.println("讀完成");// 處理完第一個 accept 時,需要再次調用 accept 方法來處理下一個 accept 事件ssc.accept(null, this);}/*** 當接受操作失敗時被調用。* 打印異常堆棧跟蹤。** @param exc        引發的異常* @param attachment 接受操作的附加上下文*/@Overridepublic void failed(Throwable exc, Object attachment) {exc.printStackTrace();}}
}

5.2 客戶端

同 4.2

5.3 運行截圖

在這里插入圖片描述
在這里插入圖片描述

6. Channel / Buffer

6.1 Channel

Channel: 傳輸數據的通道

其實和數據流挺像的,不過數據流是單向的而Channel 是雙向的,可以向channel中寫數據,也可以從channel中讀取數據

NIO 基礎組件之 Channel

6.2 ByteBuffer

ByteBuffer是Buffer子類,是字節緩沖區,特點如下所示。

大小不可變。一旦創建,無法改變其容量大小,無法擴容或者縮容;
讀寫靈活。內部通過指針移動來實現靈活讀寫;
支持堆上內存分配和直接內存分配

一文搞懂ByteBuffer使用與原理

參考文獻

  • UNIX 網絡編程 卷1: 套接字聯網API
  • TCP/IP網絡編程 尹圣雨 著 金國哲 譯
  • Linux IO模式及 select、poll、epoll詳解
  • 淺談select,poll和epoll的區別
  • 黑馬 Netty 課程

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/22847.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/22847.shtml
英文地址,請注明出處:http://en.pswp.cn/web/22847.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C++筆試強訓day39

目錄 1.神奇的字母&#xff08;二&#xff09; 2.字符編碼 3.最少的完全平方數 1.神奇的字母&#xff08;二&#xff09; 鏈接https://ac.nowcoder.com/acm/problem/205832 看輸出描述即可知輸出次數最多的那個字母即可。 哈希表直接秒了&#xff1a; #include <iostre…

一維時間序列突變檢測方法(小波等,MATLAB R2021B)

信號的突變點檢測問題是指在生產實踐中&#xff0c;反映各種系統工作狀態的信號&#xff0c;可能因為受到不同類型的噪聲或外界干擾而發生了信號突變&#xff0c;導致嚴重失真的信號出現&#xff0c;因此必須探測突變出現的起點和終點。研究目的在于設計出檢測方案&#xff0c;…

CPU內部結構窺探·「2」

從一條匯編加法指令出發&#xff0c;分析cpu內部發生了什么&#xff1f; 本文將詳細剖析ARMv8架構中加法指令的執行過程&#xff0c;深入理解其在CPU上的運行機制。 ARMv8匯編基礎 在ARMv8匯編語言中&#xff0c;加法指令ADD的基本格式如下&#xff1a; ADD destination, s…

【python】python租房數據分析可視化(源碼+數據+報告)【獨一無二】

&#x1f449;博__主&#x1f448;&#xff1a;米碼收割機 &#x1f449;技__能&#x1f448;&#xff1a;C/Python語言 &#x1f449;公眾號&#x1f448;&#xff1a;測試開發自動化【獲取源碼商業合作】 &#x1f449;榮__譽&#x1f448;&#xff1a;阿里云博客專家博主、5…

在Go語言中如何使用變量

1. 變量 Go 中的變量是標識符。例如&#xff0c;我們可能需要存儲客戶的電子郵件地址&#xff0c;但還需要確保它是有效的。這種情況下&#xff0c;可以創建一個名為 email 的變量來存儲電子郵件的值。電子郵件地址可以分配給 email 變量。 變量引用一個內存地址&#xff0c;賦…

OpenCV學習(4.3) 圖像閾值

1.目的 在本教程中&#xff1a; 你會學到簡單閾值法&#xff0c;自適應閾值法&#xff0c;以及 Otsu 閾值法(俗稱大津法)等。你會學到如下函數&#xff1a;**cv.threshold&#xff0c;cv.adaptiveThreshold** 等。 2.簡單閾值法 此方法是直截了當的。如果像素值大于閾值&am…

word2016版本中同時顯示多個頁面

為了方便查看word內容&#xff0c;我們會將多個頁面同時顯示。 對于2016版&#xff0c;操作方法如下&#xff1a; 視圖 ---》多頁

Jan任意文件讀取/下載和上傳漏洞

自從ChatGPT橫空出世以來&#xff0c;我一直想找一個可以自己訓練的AI大模型&#xff0c;然而在使用Jan的過程中&#xff0c;數據包中傳遞的參數引起了我的興趣&#xff0c;簡單嘗試后發現了任意文件讀取和任意文件上傳漏洞。 簡介 Jan是ChatGPT的開源替代品&#xff0c;它在…

vuInhub靶場實戰系列--bulldog-1

免責聲明 本文檔僅供學習和研究使用,請勿使用文中的技術源碼用于非法用途,任何人造成的任何負面影響,與本人無關。 目錄 免責聲明前言一、環境配置1.1 靶場信息1.2 靶場配置 二、信息收集2.1 主機發現2.1.1 netdiscover2.1.2 nmap主機掃描2.1.3 arp-scan主機掃描 2.2 端口掃描…

友思特案例 | 自動快速定位:使用波長選擇器測量濾光片的關鍵光學性能指標

導讀 光學濾光片檢測的手動調節校準的傳統方法存在諸多不確定誤差和高昂的成本消耗。友思特全自動可調諧光源檢測解決方案&#xff0c;可全自動調節波長帶寬&#xff0c;快速收集光譜數據&#xff0c;縮短檢測時間、降低質檢成本&#xff0c;實現極高的準確率和快速檢測效率。…

RA8D1-Vision Board上OSPI-Flash實踐

Vision-Board 開發板是 RT-Thread 推出基于瑞薩 Cortex-M85 架構 RA8D1 芯片,擁有Helium和TrustZone技術的加持,性能非常強大。 內核:480 MHz Arm Cortex-M85,包含Helium和TrustZone技術 存儲:集成2MB/1MB閃存和1MB SRAM(包括TCM,512KB ECC保護) 外設:兼容xSPI的四線O…

gorse修改開源項目后,如何使用Docker compose發布

代碼修改 git checkout v0.4.15 修改代碼后提交。 鏡像構建 export GOOSlinux export GOARCHamd64 export GOMAXPROCS8go build -ldflags"-s -w -X github.com/zhenghaoz/gorse/cmd/version.Version$(git describe --tags $(git rev-parse HEAD)) -X github.com/zhengh…

如何在強數據一致性要求下設計數據庫的高可用架構

在高可用的三大架構設計(基于數據層的高可用、基于業務層的高可用,以及融合的高可用架構設計)中。僅僅解決了業務連續性的問題:也就是當服務器因為各種原因,發生宕機,導致MySQL 數據庫不可用之后,快速恢復業務。但對有狀態的數據庫服務來說,在一些核心業務系統中,比如…

運營商卷大模型,云廠商霸主地位不保?

文&#xff5c;藝 思 編&#xff5c;王一粟 經過了2023年的小試牛刀&#xff0c;2024年&#xff0c;三大運營商帶著大模型一路狂飆。 剛剛過去的5月&#xff0c;中國電信、中國移動、中國聯通三大運營商集體完成了新一輪的大模型進化&#xff0c;特別是圍繞大模型的研發與…

【區分vue2和vue3下的element UI TimePicker 時間選擇器組件,分別詳細介紹屬性,事件,方法如何使用,并舉例】

在 Vue 2 中&#xff0c;我們通常使用 Element UI 來實現時間選擇器&#xff08;TimePicker&#xff09;組件。然而&#xff0c;在 Vue 3 中&#xff0c;Element UI 沒有官方支持 Vue 3 的版本。但是&#xff0c;有一個名為 Element Plus 的庫&#xff0c;它是 Element UI 的 V…

04--Tomcat

前言&#xff1a;本章整理tomcat的知識點&#xff0c;tomcat知識點相較nginx比較少&#xff0c;但是也是運維必會的軟件&#xff0c;這里結合實際項目整理一下。 1、tomcat簡介 Tomcat 服務器是一個免費的開放源代碼的Web 應用服務器&#xff0c;屬于輕量級應用服務器&#x…

強烈安利10款手機App!

AI視頻生成&#xff1a;小說文案智能分鏡智能識別角色和場景批量Ai繪圖自動配音添加音樂一鍵合成視頻https://aitools.jurilu.com/ 1.聽書神器——昊昊聽書 昊昊聽書app是一款專門為用戶提供有聲讀物的應用程序。它不僅提供了各種類型的有聲書籍&#xff0c;還有各種知名的電…

pw命令1

1、查看集群狀態命令 gs_om -t status --detail 2、備節點升主&#xff08;本例子升2節點為主&#xff09; date && time cm_ctl switchover -n 2 -D /database/panweidb/data 3、cm_ctl是全局的&#xff0c;在一個節點運行 cm_ctl stop && cm_ctl start 就重…

鑄鐵機械5G智能工廠工業物聯數字孿生平臺,推進制造業數字化轉型

鑄鐵機械5G智能工廠工業物聯數字孿生平臺&#xff0c;推進制造業數字化轉型。工業物聯數字孿生平臺以5G技術為基礎&#xff0c;通過工業物聯網連接鑄鐵機械生產過程中的各個環節&#xff0c;運用數字孿生技術構建虛擬工廠&#xff0c;實現生產過程的實時監測、模擬與優化&#…

垃圾回收算法

垃圾回收基于“對象不再使用”的原則&#xff0c;自動檢測并回收不再被引用的對象。JVM通過跟蹤對象的引用關系來判斷對象是否仍在使用中。當一個對象沒有任何引用指向它時&#xff0c;垃圾回收器就會將其標記為可回收對象。 垃圾回收的工作機制 標記-清除&#xff08;Mark-S…