C#多線程開發詳解

C#多線程開發詳解

  • 持續更新中。。。。。
  • 一、為什么要使用多線程開發
    • 1.提高性能
    • 2.響應性
    • 3.資源利用
    • 4.任務分解
    • 5.并行計算
    • 6.實時處理
  • 二、多線程開發缺點
    • 1.競態條件
    • 2.死鎖和饑餓
    • 3.調試復雜性
    • 4.上下文切換開銷
    • 5.線程安全性
  • 三、多線程開發涉及的相關概念
    • 常用概念
      • (1)lock
      • (2)查看當前工作線程信息
      • (3)主線程、前臺線程、后臺線程
    • 1.Thread(線程)
      • (1)創建線程
      • (2) 線程同步
      • (3)線程異步
    • 2.ThreadPool(線程池)
    • 3.Task(任務)
      • (1)Task與Thead的關系
    • 4.Task Parallel Library (TPL)(任務并行庫)
    • 5.Async/Await(異步/等待)
    • 6.Monitor(監視器)
    • 7.Semaphore(信號量)
    • 8.SemaphoreSlim
    • 9.AutoResetEvent(自動復位事件)
    • 10.ManualResetEvent(手動復位事件)
    • 11.CancellationToken(取消標記)
    • 12.volatile(易失性修飾符)
    • 13.Mutex(互斥鎖)
    • 14.ReaderWriterLock(讀寫鎖)
    • 15.ReaderWriterLockSlim(輕量級讀寫鎖)
    • 16.SpinLock
    • 17.SpinWait
    • 18.Barrier(屏障)
  • 四、多線程的異常捕獲問題

持續更新中。。。。。

一、為什么要使用多線程開發

1.提高性能

多線程允許程序同時執行多個任務,從而有效利用多核處理器,加快程序的執行速度。特別是在需要處理大量計算、I/O 操作或并行任務的應用中,多線程可以顯著提高性能。

2.響應性

多線程使應用能夠同時處理多個用戶請求或事件,提高了應用的響應性。例如,多線程可以保持用戶界面的響應,即使在執行長時間操作時也能讓用戶繼續交互。

3.資源利用

多線程可以更有效地利用系統資源,如內存和網絡連接。這對于高并發服務器、網絡應用和數據處理任務特別有用。

4.任務分解

將復雜任務分解為多個小任務,每個任務在不同的線程中執行,可以簡化問題并提高可維護性。

5.并行計算

多線程可以用于并行計算,例如在科學計算、數據分析和圖像處理領域。這有助于加速大規模計算。

6.實時處理

在實時系統中,多線程可以保證任務在規定的時間內完成,從而滿足對時間敏感性的需求。

二、多線程開發缺點

1.競態條件

多線程可能會導致競態條件,即多個線程競爭訪問共享資源,可能導致數據不一致性和錯誤。

2.死鎖和饑餓

不正確的線程同步可能導致死鎖(多個線程無法繼續執行)或饑餓(某些線程無法獲取所需資源)問題。

線程1,2啟動,分別占用鎖lock1,lock2。之后線程1請求lock2,但是線程2已經占用lock2,線程1無法繼續執行,進入等待。線程2請求lock1,但是線程1已經占用lock1,線程2無法繼續執行,進入等待。這里陷入死鎖,線程1,線程2,都在等待對方釋放鎖來給自己使用,程序一直無法運行,一直在等待中。

using System;
using System.Threading;class DeadlockExample
{static object lock1 = new object();static object lock2 = new object();static void Main(){Thread thread1 = new Thread(Method1);Thread thread2 = new Thread(Method2);thread1.Start();thread2.Start();thread1.Join();thread2.Join();Console.WriteLine("Main thread finished.");}static void Method1(){lock (lock1){Console.WriteLine("Method1 acquired lock1.");Thread.Sleep(1000);Console.WriteLine("Method1 trying to acquire lock2.");lock (lock2){Console.WriteLine("Method1 acquired lock2.");}}}static void Method2(){lock (lock2){Console.WriteLine("Method2 acquired lock2.");Thread.Sleep(1000);Console.WriteLine("Method2 trying to acquire lock1.");lock (lock1){Console.WriteLine("Method2 acquired lock1.");}}}
}

3.調試復雜性

多線程程序的調試和錯誤跟蹤可能會更加復雜,因為線程間的交互和排錯可能變得更難。

4.上下文切換開銷

上下文切換(Context Switching)是多線程環境中的一種操作,指的是在一個 CPU 核心上切換正在執行的線程,從當前線程的執行上下文(包括寄存器狀態、程序計數器等)切換到另一個線程的執行上下文, 線程的切換需要額外的開銷,因此在某些情況下,過多的線程可能會導致性能下降。

  1. 當一個線程的時間片(時間片輪轉調度算法)用完,操作系統需要掛起該線程并切換到另一個線程。
  2. 當一個線程主動放棄 CPU,例如通過調用 Thread.Sleep()、Thread.Yield() 或等待某個事件時
    3.當一個線程被高優先級的線程搶占

上下文切換的過程涉及以下步驟:

  1. 保存當前線程的上下文: 操作系統將當前線程的寄存器狀態、程序計數器等信息保存到該線程的內存空間中,以便稍后能夠恢復該線程的執行
    2.恢復目標線程的上下文: 操作系統從目標線程的內存空間中恢復寄存器狀態、程序計數器等信息,準備讓目標線程繼續執行。
  2. 切換內核堆棧: 每個線程都有自己的內核堆棧,上下文切換時,操作系統會切換內核堆棧,以確保線程的隔離性。

上下文切換開銷指的是從一個線程切換到另一個線程的過程中所涉及的時間和資源開銷。這些開銷主要包括以下幾個方面:

  1. 寄存器保存和恢復: 當線程切換時,操作系統需要保存當前線程的寄存器狀態,然后恢復目標線程的寄存器狀態。這涉及到大量的數據拷貝和計算。
    2.內存訪問: 上下文切換過程中需要頻繁訪問內存,包括將寄存器狀態和其他上下文信息寫入內存,以及從內存中讀取目標線程的上下文信息。
    3.調度開銷: 操作系統需要決定要切換到哪個線程,這涉及到調度算法的開銷,包括選擇合適的線程并進行必要的線程隊列操作。
    4.TLB(Translation Lookaside Buffer)失效: 當線程切換時,虛擬內存的映射可能會發生變化,導致 TLB 緩存失效,從而增加了內存訪問的開銷。

上下文切換開銷會影響系統的整體性能,特別是在高并發、頻繁切換的情況下。因此,在設計多線程應用程序時,需要考慮如何減少上下文切換的發生,以提高程序的執行效率。一些方法包括:

  1. 使用線程池:線程池可以減少線程的創建和銷毀,從而減少上下文切換的頻率。
  2. 合理設置線程數量:避免創建過多線程,以減少不必要的上下文切換。
    3.使用異步編程模型:使用異步操作和任務可以減少線程的使用,從而減少上下文切換。

5.線程安全性

多線程編程需要謹慎處理線程安全性,以避免數據競爭和共享資源的沖突。

三、多線程開發涉及的相關概念

常用概念

(1)lock

在 C# 中,lock 關鍵字用于實現線程同步,以確保在多線程環境中對共享資源的訪問是安全的。lock 關鍵字會創建一個互斥鎖(也稱為監視器鎖),只有一個線程可以獲得該鎖,從而確保在同一時間只有一個線程能夠執行被 lock 包圍的代碼塊。

lock (lockObject)
{// 在這里執行需要同步的代碼
}

其中,lockObject 是一個用于同步的對象。它可以是任何引用類型的對象,但通常是一個專門用于同步的對象。多個線程可以共享同一個 lockObject,并且只有一個線程能夠獲得鎖并執行被 lock 包圍的代碼塊。

class Program
{static readonly object lockObject = new object(); // 同步對象static void Main(string[] args){for (int i = 0; i < 5; i++){ThreadStart start = () =>{lock (lockObject){Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} is in the critical section.");Thread.Sleep(1000);Console.WriteLine($"Thread {Thread.CurrentThread.ManagedThreadId} has exited the critical section.");}};Thread thread = new Thread(start);thread.Start();}Console.ReadKey();}
}

在這里插入圖片描述

(2)查看當前工作線程信息

可以使用 Thread.CurrentThread 屬性來獲取當前正在執行的線程的信息。這個屬性返回一個表示當前線程的 Thread 對象,你可以使用它來查詢線程的各種屬性和狀態。

Thread 類還提供了 Priority 屬性,允許你設置線程的優先級。然而,操作系統不一定會完全遵循線程的優先級,這取決于操作系統的調度機制。

線程可以分為前臺線程和后臺線程。前臺線程是主線程的一部分,如果所有前臺線程都完成,程序將終止。后臺線程是在后臺運行的線程,如果所有前臺線程都完成,程序會立即終止,不會等待后臺線程完成。

using System;
using System.Threading;class Program
{static void Main(){Thread currentThread = Thread.CurrentThread;Console.WriteLine($"Thread ID: {currentThread.ManagedThreadId}");Console.WriteLine($"Thread Name: {currentThread.Name}");Console.WriteLine($"Is Thread Background: {currentThread.IsBackground}");Console.WriteLine($"Thread Priority: {currentThread.Priority}");Console.WriteLine($"Thread State: {currentThread.ThreadState}");}
}

在這里插入圖片描述

(3)主線程、前臺線程、后臺線程

主線程(Main Thread),它是程序的入口點,并且在程序啟動時自動創建。主線程負責啟動其他線程,并且通常是其他線程的父線程,但并不是所有線程都是主線程的子線程。

線程之間沒有嚴格的父子關系。主線程和其他線程之間通常是平等的,沒有直接的父子關系。但是,你可以通過編程來模擬一種線程間的層次關系,使得某些線程在邏輯上看起來是其他線程的子線程。這通常涉及線程的創建、協調和通信

以下是一個示例,演示了如何通過邏輯上的組織來模擬一種主線程和子線程的關系:

using System;
using System.Threading;class Program
{static void Main(){Console.WriteLine("Main thread starts.");Thread parentThread = new Thread(ParentThreadMethod);parentThread.Start();parentThread.Join();Console.WriteLine("Main thread ends.");}static void ParentThreadMethod(){Console.WriteLine("Parent thread starts.");Thread childThread = new Thread(ChildThreadMethod);childThread.Start();childThread.Join();Console.WriteLine("Parent thread ends.");}static void ChildThreadMethod(){Console.WriteLine("Child thread starts.");Thread.Sleep(2000);Console.WriteLine("Child thread ends.");}
}

前臺線程(Foreground Threads):
這些線程是由主線程或其他前臺線程創建的,它們的生命周期獨立于主線程,但它們不是主線程的子線程。前臺線程與主線程之間的關系是平級的。當所有前臺線程都執行完畢時,程序才會退出,無論主線程是否結束。

  1. 生命周期:
    前臺線程的生命周期不受其他線程的影響。即使主線程退出,前臺線程仍然可以繼續執行,直到完成。
  2. 程序退出:
    如果程序中還有前臺線程在運行,主程序將等待所有前臺線程完成后才會退出。主線程也是前臺線程,如果主線程退出,會等待其他前臺線程完成后再退出。
  3. 影響程序:
    前臺線程會阻塞程序的退出,直到所有前臺線程完成。這可能會影響程序的退出速度。
  4. 默認類型:
    == 通過 new Thread(…) 創建的線程默認是前臺線程。==

在這里插入圖片描述

后臺線程(Background Threads):
這些線程也是由主線程或其他前臺線程創建的,它們同樣是平級的,不是主線程的子線程。后臺線程與主線程之間的關系也是平級的。當所有前臺線程結束,程序會退出,同時會終止所有后臺線程,不管后臺線程是否執行完畢。

  1. 生命周期:
    后臺線程的生命周期受到主線程的影響。如果所有前臺線程(包括主線程)都已經完成,程序會立即退出,同時終止后臺線程,不管后臺線程是否執行完畢。
  2. 程序退出:
    如果程序中只剩下后臺線程在運行,即使主線程結束,程序也會立即退出,不會等待后臺線程完成。
  3. 影響程序:
    后臺線程不會阻塞程序的退出,它們對程序的退出速度沒有影響。
  4. 設置后臺線程:
    可以通過設置線程的 IsBackground 屬性為 true 將線程設置為后臺線程。通過 Thread 類創建的線程可以使用這個屬性進行設置。

在這里插入圖片描述

使用場景:

  1. 前臺線程通常用于執行一些關鍵任務,確保這些任務的完成。例如,在主線程需要等待其他線程的結果時,可以使用前臺線程。
  2. 后臺線程通常用于執行一些非關鍵性的任務,如日志記錄、監控等。它們不會阻止程序的退出,適用于在程序退出時不需要保證任務完全執行的情況。

錯誤使用后臺線程,可能引起資源泄露或意外行為

  1. 資源泄露:
    如果后臺線程在程序退出時還在執行,可能會導致資源無法正確釋放。例如,如果后臺線程打開了文件、網絡連接或其他資源,但程序退出時這些資源沒有被正確關閉,就會發生資源泄露。
  2. 不完整的操作:
    如果后臺線程執行一些需要完整執行的操作,例如數據的寫入、狀態的更新等,但程序退出時這些操作未完成,可能會導致數據不一致或損壞。
  3. 異常處理:
    后臺線程的異常不會被捕獲并傳播到主線程,可能會導致未處理的異常,影響程序的穩定性。
    4.線程同步:
    在程序退出時,后臺線程可能還在等待某些同步操作完成,但這些操作可能無法在后臺線程終止之前完成,可能會導致死鎖或其他線程同步問題。

1.Thread(線程)

表示一個執行線程,用于并行執行代碼。可以使用 Thread 類來創建和管理線程。線程是執行程序的最小單位,多線程編程允許程序同時執行多個任務,從而提高性能和響應性。

Thread 類是 C# 中用于線程操作的基礎類之一。然而,對于更高級的線程編程需求,你可能會使用 Task、ThreadPool、異步編程模型等更高級的機制,以便更好地管理和協調多線程操作。

Thead常用方法

  1. Start(): 啟動線程,使其開始執行指定的方法。
  2. Join(): 阻塞當前線程,直到目標線程完成。
  3. Abort(): 強制終止線程的執行。不建議使用,因為可能導致資源泄漏或不穩定的狀態。
  4. Sleep(int millisecondsTimeout): 使當前線程休眠指定的毫秒數。
  5. IsAlive(): 返回一個布爾值,指示線程是否處于活動狀態。
  6. Interrupt(): 中斷線程,引發一個 ThreadInterruptedException 異常。
  7. Suspend() 和 Resume(): 已過時,不推薦使用。用于暫停和恢復線程的執行。
  8. GetDomain() 和 GetDomainID(): 獲取線程所屬的應用程序域和域標識符。
  9. SetApartmentState(ApartmentState state): 設置線程的單元狀態,用于控制線程的COM互操作行為。
  10. GetCurrentThreadId() 和 GetDomainID(): 獲取當前線程的唯一標識符。
  11. Interrupt(): 中斷線程的等待狀態,引發 ThreadInterruptedException 異常。
  12. Yield(): 提示系統允許其他等待線程運行。
  13. Name 和 CurrentThread.Name: 獲取或設置線程的名稱。
  14. SetData 和 GetData: 在線程范圍內設置和獲取線程本地存儲數據。
  15. Start(ParameterizedThreadStart) 和 Start(ParameterizedThreadStart, Object): 啟動線程并傳遞參數給線程方法。
  16. TrySetApartmentState(ApartmentState): 嘗試設置線程的單元狀態,返回是否成功。
  17. StartNew(Action) 和 StartNew(Action, CancellationToken): 使用 Task 類來啟動線程。

這些方法提供了各種線程管理和操作的能力。然而,需要注意,一些方法已經過時,不推薦使用,而且一些方法可能會涉及多線程編程的復雜性,需要謹慎使用。在編寫多線程應用程序時,確保仔細閱讀文檔并根據需求選擇適當的方法。

(1)創建線程

通常,你需要傳遞一個方法作為線程的入口點,然后調用 Start 方法來啟動線程。

using System;
using System.Threading;class Program
{static void Main(){Thread thread = new Thread(WorkerMethod);thread.Start(); // 啟動線程}static void WorkerMethod(){Console.WriteLine("Thread is running.");}
}

(2) 線程同步

在多線程環境中,線程同步是一種確保多個線程協調工作的機制。Thread 類提供了 Join 方法,允許一個線程等待另一個線程完成。這在需要等待某個線程的結果時特別有用。

using System;
using System.Threading;class Program
{static void Main(){Thread currentThread = Thread.CurrentThread;Console.WriteLine($"Thread ID: {currentThread.ManagedThreadId}");Thread thread = new Thread(WorkerMethod);thread.Start();// 主線程等待子線程完成thread.Join();Console.WriteLine("Thread has finished.");}static void WorkerMethod(){Thread currentThread = Thread.CurrentThread;Console.WriteLine($"Thread ID: {currentThread.ManagedThreadId}");Console.WriteLine("Thread is running.");Thread.Sleep(2000); // 模擬耗時操作}
}

在這里插入圖片描述

(3)線程異步

using System;
using System.Threading;class Program
{static void Main(){Thread currentThread = Thread.CurrentThread;Console.WriteLine($"Thread ID: {currentThread.ManagedThreadId}");Thread thread = new Thread(WorkerMethod);thread.Start();// 主線程等待子線程完成//thread.Join();Console.WriteLine("Thread has finished.");//這里子線程雖然還沒有處理完,但是直接返回了,沒有繼續等待子線程,但是子線程還在繼續處理工作,沒有出現阻塞現象return "ok";}static void WorkerMethod(){Thread currentThread = Thread.CurrentThread;Console.WriteLine($"Thread ID: {currentThread.ManagedThreadId}");Console.WriteLine("Thread is running.");Thread.Sleep(10000); // 模擬耗時操作//這里在主線程結束后,繼續在處理10s后打印Thread is WordEnd;Console.WriteLine("Thread is WordEnd.");}
}

可以思考下,主線程返回成功了,但是子線程執行失敗了,這可怎么辦?

在這里插入圖片描述

2.ThreadPool(線程池)

是一個用于管理和重用線程的機制,可以使用 ThreadPool 類來執行異步任務。

3.Task(任務)

表示一個異步操作,可以使用 Task 類或 Task.Run 方法來創建和管理任務。

(1)Task與Thead的關系

4.Task Parallel Library (TPL)(任務并行庫)

是 C# 中用于并行編程的高級庫,用于處理異步和并行操作,包括數據并行和任務并行。

5.Async/Await(異步/等待)

是 C# 5.0 引入的異步編程模型,用于創建和管理異步方法和操作。

6.Monitor(監視器)

是用于實現線程同步的一種機制,用于保護共享資源,避免競態條件。可以使用 Monitor 類或 lock 關鍵字來實現。

首先lock和Minitor有什么區別呢?
其實lock在IL代碼中會被翻譯成Monitor。也就是Monitor.Enter(obj)和Monitor.Exit(obj).

lock(obj)
{}//等價為:
try{    Monitor.Enter(obj)
}catch()
{}
finally
{Monitor.Exit(obj)
}

7.Semaphore(信號量)

用于控制并發訪問資源的數量,可以使用 Semaphore 類來創建和管理信號量。

8.SemaphoreSlim

是 Semaphore 的改進版本,提供更好的性能和可伸縮性。

9.AutoResetEvent(自動復位事件)

用于線程同步,允許一個線程等待另一個線程發出信號。

10.ManualResetEvent(手動復位事件)

用于線程同步,允許一個線程等待多個線程發出信號。

11.CancellationToken(取消標記)

用于在異步操作中請求取消操作,可以在異步方法中傳遞給取消標記。

12.volatile(易失性修飾符)

用于標記字段,指示編譯器不應該對標記字段進行優化,以確保多線程環境下的正確性。

13.Mutex(互斥鎖)

是一種用于實現線程同步的機制,用于保護共享資源,防止多個線程同時訪問。

14.ReaderWriterLock(讀寫鎖)

允許多個線程同時讀取共享資源,但只允許一個線程寫入資源。適用于讀操作頻繁、寫操作較少的場景。

15.ReaderWriterLockSlim(輕量級讀寫鎖)

是 ReaderWriterLock 的改進版本,提供更好的性能和可伸縮性。

16.SpinLock

是一種自旋鎖,用于短時間內的臨界區保護。它使用忙等待來嘗試獲取鎖,適用于臨界區很小的情況。

17.SpinWait

用于在自旋等待期間執行自旋操作,可以根據不同的條件進行自旋。

18.Barrier(屏障)

允許多個線程在一個點上等待,直到所有線程都達到該點。適用于需要所有線程協調同步的場景。

四、多線程的異常捕獲問題

相關文章

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

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

相關文章

NanoPi NEO移植LVGL8.3.5到1.69寸ST7789V屏幕

移植前準備 移植好fbtft屏幕驅動 參考鏈接&#xff1a;友善之臂NanoPi NEO利用fbtft驅動點亮1.69寸ST7789V2屏幕 獲取源碼 名稱地址描述lvglhttps://github.com/lvgl/lvgl.gitlvgl-8.3.5lv_drivershttps://github.com/lvgl/lv_drivers.gitlv_drivers-6.1.1 創建工程目錄 創…

RF PCB的9條改進型建議

1.小功率的RF的PCB設計中,主要使用標準的FR4材料(絕緣特性好、材質均勻、介電常數ε=4,10%)。主要使用4層~6層板,在成本非常敏感的情況下可以使用厚度在1mm以下的雙面板,要保證反面是一個完整的地層,同時由于雙面板的厚度在1mm以上,使得地層和信號層之間的FR4介質較厚,…

Linux | curl命令調用接口時查看調用時長和詳情

關注wx&#xff1a; CodingTechWork 引言 在服務器中通過curl命令調用接口時&#xff0c;我們經常需要分析一些時長。本文主要總結兩種方式進行處理。 curl命令 使用time命令 time curl -k -u <username>:<password> https://127.0.0.1/xxxx -vvv 使用文本 編…

HTML <span> 標簽

定義和用法 <span> 標簽被用來組合文檔中的行內元素。 瀏覽器支持 元素ChromeIEFirefoxSafariOpera<span>YesYesYesYesYes所有瀏覽器都支持 <span> 標簽。 HTML 與 XHTML 之間的差異 NONE 提示和注釋: 提示:請使用 <span> 來組合行內元素,以便…

旋轉圖像(旋轉矩陣)

原題鏈接 旋轉圖像備戰技術面試&#xff1f;力扣提供海量技術面試資源&#xff0c;幫助你高效提升編程技能&#xff0c;輕松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/rotate-image/ 算法分析 若矩陣的行列數為N&#xff0c;設i表示行索引&#xff0c;i屬…

win10中Docker安裝、構建鏡像、創建容器、Vscode連接實例

Docker方便一鍵構建項目所需的運行環境&#xff1a;首先構建鏡像(Image)。然后鏡像實例化成為容器(Container)&#xff0c;構成項目的運行環境。最后Vscode連接容器&#xff0c;方便我們在本地進行開發。下面以一個簡單的例子介紹在win10中實現&#xff1a;Docker安裝、構建鏡像…

Flutter BottomSheet 三段式拖拽

BottomSheetBehavior 追蹤 BottomSheet系統默認實現效果準備要實現的功能點&#xff1a;定義三段式狀態&#xff1a;BottomSheetBehavoir閥值定義1. 未達到滾動閥值&#xff0c;恢復狀態2. 達到滾動閥值&#xff0c;更新狀態 前面倒是有講過Android原生的BottomSheetBehavior&a…

Flask 框架集成Bootstrap

前面學習了 Flask 框架的基本用法&#xff0c;以及模板引擎 Jinja2&#xff0c;按理說可以開始自己的 Web 之旅了&#xff0c;不過在啟程之前&#xff0c;還有個重要的武器需要了解一下&#xff0c;就是著名的 Bootstrap 框架和 Flask 的結合&#xff0c;這將大大提高開發 Web …

國產數據庫-內核特性-低基數全局字典

國產數據庫-內核特性-StarRocks低基數全局字典 StarRocks2.0引入了低基數全局字典&#xff0c;可以通過全局字典將字符串的相關操作轉換成整型相關操作&#xff0c;大大提升查詢性能。 1、低基數字典 對于利用整型替代字符串進行處理&#xff0c;通常使用字典編碼進行優化。Sta…

人大金倉助力某大型金融機構業務系統異地容災優化升級

日前&#xff0c;人大金倉助力某大型金融機構應收賬款融資服務平臺異地容災項目順利上線&#xff0c;保證了平臺系統運行的連續性和數據安全&#xff0c;為充分發揮平臺的融資功能&#xff0c;緩解中小微企業融資難提供了強有力的保障。 “ 緩解中小微企業融資難 某大型金融機構…

【MySQL--->數據庫操作】

文章目錄 [TOC](文章目錄) 一、操作語句1.增2.刪3.改4.查5.備份 二、字符集與校驗規則 一、操作語句 1.增 語句格式:create database [if no exists]數據庫名[create_specification [,create_specification] …]; 中括號內是可選項,if no exists是指如果數據庫不存在就創建,存…

STM32 F103C8T6學習筆記7:雙機無線串口通信

今日嘗試配通倆個C8T6單片機之間的無線串口通信&#xff0c;文章提供原理&#xff0c;源碼&#xff0c;測試效果圖&#xff0c;測試工程下載&#xff1a; 目錄 傳輸不規范問題&#xff1a; 串口通信資源&#xff1a; 單個串口資源理解&#xff1a; 單片機串口資源&#xf…

Redis的單線程與多線程

Redis的核心處理邏輯一直都是單線程 有一些分支模塊是多線程(某些異步流程從4.0開始用的多線程&#xff0c;例如UNLINK、FLUSHALL ASYNC、FLUSHDB ASYNC等非阻塞的刪除操作。網絡I/O解包從6.0開始用的是多線程;) 為什么是單線程 多線程多好啊可以利用多核優勢 官方給的解釋 …

UI自動化環境的搭建(python+pycharm+selenium+chrome)

最近在做一些UI自動化的項目&#xff0c;為此從環境搭建來從0到1&#xff0c;希望能夠幫助到你&#xff0c;同時也是自我的梳理。將按照如下進行開展&#xff1a; 1、python的下載、安裝&#xff0c;python環境變量的配置。 2、pycharm開發工具的下載安裝。 3、selenium的安裝。…

Leetcode34 在排序數組中查找元素的第一個和最后一個位置

給你一個按照非遞減順序排列的整數數組 nums&#xff0c;和一個目標值 target。請你找出給定目標值在數組中的開始位置和結束位置。 如果數組中不存在目標值 target&#xff0c;返回 [-1, -1]。 你必須設計并實現時間復雜度為 O(log n) 的算法解決此問題。 代碼&#xff1a; c…

如何使用 Go 獲取 URL 的參數,以及使用時的問題

Go 獲取 URL 參數也很容易&#xff0c;但是由于 Go 有嚴格的數據類型和錯誤管理&#xff0c;所以在使用時會些微有些復雜。所以本文不僅會講如何獲取 URL 的參數&#xff0c;也會講在使用時的一些問題。 首先假設 URL 是https://www.example.com/?keywordabc&id12。 其他…

java中函數式接口、Stream流、方法引用、junit單元測試、反射、注解

函數式接口&#xff1a; 在java中有且僅有一個抽象方法的接口稱為函數式接口&#xff0c;但是可以包含其它的默認的或靜態的方法。 格式&#xff1a; 修飾符 interface 接口名稱 {public abstract 返回值類型 方法名稱(可選參數);// 其他非抽象方法 }函數式接口&#xff1a;…

服務器安全維護注意事項有哪些?

服務器的安全關系著公司整個網絡以及所有數據的安全&#xff0c;我們該如何做好服務器后續的安全維護呢?河南億恩科技股份有限公司&#xff0c;專注服務器托管23年&#xff0c;不僅是國內專業的互聯網基礎應用服務提供商之一&#xff0c;還是國家工信部認定的綜合電信服務運營…

OpenJDK Maven 編譯出錯: package jdk.nashorn.internal.runtime.logging does not exist

前言 OpenJDK 1.8.0Maven 3.8.5TencentOS Server 3.1 錯誤信息 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project tour-common: Compilation failure: Compilation failure: [ERROR] /opt/tour-c…

JavaScript預編譯機制

變量預編譯 任何變量&#xff0c;如果未經聲明就賦值&#xff0c;此變量是屬于 window 的屬性&#xff0c;而且不會做變量提升&#xff0c;無論在哪個作用域內賦值。比如說直接寫 console.log(a)肯定會報錯&#xff0c;提示找不到 a。但如果直接寫 a 100就不會報錯&#xff0…