主頁 > 軟體設計 > java面試整理(每天十個)2021-02-16(執行緒相關)

java面試整理(每天十個)2021-02-16(執行緒相關)

2021-02-17 12:19:05 軟體設計

從網上收集整理了面試題,雖然整理了但是好多都記不住,需要每天鞏固,

一、什么是執行緒安全

當多個執行緒訪問某一個類(物件或方法)時,物件對應的公共資料區始終都能表現正確,那么這個類(物件或方法)就是執行緒安全的,

執行緒安全的代碼是多個執行緒同時執行也能正常作業的代碼

如果一段代碼可以保證多個執行緒訪問的時候正確操作共享資料,那么它是執行緒安全的,

二、創建執行緒的方式

繼承Thread類創建執行緒
實作Runnable介面創建執行緒
使用Callable和Future創建執行緒
使用執行緒池創建(使用java.util.concurrent.Executor介面)

1、繼承Thread類創建執行緒類

(1)定義Thread類的子類,并重寫該類的run方法,該run方法的方法體就代表了執行緒要完成的任務,因此把run()方法稱為執行體,

(2)創建Thread子類的實體,即創建了執行緒物件,

(3)呼叫執行緒物件的start()方法來啟動該執行緒,

2、通過實作Runnable介面創建執行緒類

(1)定義runnable介面的實作類,并重寫該介面的run()方法,該run()方法的方法體同樣是該執行緒的執行緒執行體,

(2)創建 Runnable實作類的實體,并依此實體作為Thread的target來創建Thread物件,該Thread物件才是真正的執行緒物件,

(3)呼叫執行緒物件的start()方法來啟動該執行緒,

3、通過Callable和Future創建執行緒

(1)創建Callable介面的實作類,并實作call()方法,該call()方法將作為執行緒執行體,并且有回傳值,

(2)創建Callable實作類的實體,使用FutureTask類來包裝Callable物件,該FutureTask物件封裝了該Callable物件的call()方法的回傳值,

(3)使用FutureTask物件作為Thread物件的target創建并啟動新執行緒,

(4)呼叫FutureTask物件的get()方法來獲得子執行緒執行結束后的回傳值,

4、使用執行緒池創建(使用java.util.concurrent.Executor介面)

三、Runnable和Callable的區別

  • Runnable沒有回傳值;Callable可以回傳執行結果,是個泛型,和Future、FutureTask配合可以用來獲取異步執行的結果
  • Callable介面的call()方法允許拋出例外;Runnable的run()方法例外只能在內部消化,不能往上繼續拋

:Callalble介面支持回傳執行結果,需要呼叫FutureTask.get()得到,此方法會阻塞主行程的繼續往下執行,如果不呼叫不會阻塞,

四、wait方法和sleep方法的區別

  • sleep是Thread類的方法,wait是Object類的方法,
  • 最主要是sleep方法沒有釋放鎖,而wait方法釋放了鎖,使得其他執行緒可以使用同步控制塊或者方法(鎖代碼塊和方法鎖),
  • wait,notify和notifyAll只能在同步控制方法或者同步控制塊里面使用,而sleep可以在任何地方使用(使用范圍), sleep必須捕獲例外,而wait,notify和notifyAll不需要捕獲例外 ,
  • sleep方法是Thread類的靜態方法,呼叫此方法會讓當前執行緒暫停指定的時間,將執行機會(CPU)讓給其他執行緒,但是不會釋放鎖,因此休眠時間結束后自動恢復(程式回到就緒狀態),
  • wait是Object類的方法,呼叫物件的wait方法導致執行緒放棄CPU的執行權,同時也放棄物件的鎖(執行緒暫停執行),進入物件的等待池(wait pool),只有呼叫物件的notify或notifyAll方法才能喚醒等待池中的執行緒進入等鎖池(lock pool),如果執行緒重新獲得物件的鎖就可以進入就緒狀態,
  • wait 可以指定時間也可以不指定,指定時間 wait(time) 在 time時間內 有別的執行緒 notifyAll() 是不會喚醒到它 ,sleep 必須指定時間,

五、synchronized和ReentrantLock區別

1)Lock是一個介面,synchronized是Java中的關鍵字,synchronized是內置的語言實作;
2)synchronized發生例外時,會自動釋放執行緒占用的鎖,故不會發生死鎖現象,Lock發生例外,若沒有主動釋放,極有可能造成死鎖,故需要在finally中呼叫unLock方法釋放鎖;
3)Lock可以讓等待鎖的執行緒回應中斷,使用synchronized只會讓等待的執行緒一直等待下去,不能回應中斷
4)通過Lock可以知道有沒有成功獲取到鎖,synchronized就不靈
5)Lock可以提高多個執行緒進行讀操作的效率,

ReentrantLock是Lock的實作類,是一個互斥的同步器,在多執行緒高競爭條件下,ReentrantLock比synchronized有更加優異的性能表現

底層實作上來說,synchronized 是JVM層面的鎖,是Java關鍵字,通過monitor物件來完成(monitorenter與monitorexit),物件只有在同步塊或同步方法中才能呼叫wait/notify方法,ReentrantLock 是從jdk1.5以來(java.util.concurrent.locks.Lock)提供的API層面的鎖,

是否可手動釋放:

synchronized 不需要用戶去手動釋放鎖,synchronized 代碼執行完后系統會自動讓執行緒釋放對鎖的占用; ReentrantLock則需要用戶去手動釋放鎖,如果沒有手動釋放鎖,就可能導致死鎖現象,一般通過lock()和unlock()方法配合try/finally陳述句塊來完成,使用釋放更加靈活,

是否可中斷

synchronized是不可中斷型別的鎖,除非加鎖的代碼中出現例外或正常執行完成; ReentrantLock則可以中斷,可通過trylock(long timeout,TimeUnit unit)設定超時方法或者將lockInterruptibly()放到代碼塊中,呼叫interrupt方法進行中斷,

是否公平鎖

synchronized為非公平鎖 ReentrantLock則即可以選公平鎖也可以選非公平鎖,通過構造方法new ReentrantLock時傳入boolean值進行選擇,為空默認false非公平鎖,true為公平鎖,

鎖是否可系結條件Condition

synchronized不能系結; ReentrantLock通過系結Condition結合await()/singal()方法實作執行緒的精確喚醒,而不是像synchronized通過Object類的wait()/notify()/notifyAll()方法要么隨機喚醒一個執行緒要么喚醒全部執行緒,

鎖的物件

synchronzied鎖的是物件,鎖是保存在物件頭里面的,根據物件頭資料來標識是否有執行緒獲得鎖/爭搶鎖;ReentrantLock鎖的是執行緒,根據進入的執行緒和int型別的state標識鎖的獲得/爭搶,

兩者的共同點:
1. 都是用來協調多執行緒對共享物件、變數的訪問
2. 都是可重入鎖,同一執行緒可以多次獲得同一個鎖
3. 都保證了可見性和互斥性
兩者的不同點:
1. ReentrantLock 顯示的獲得、釋放鎖,synchronized 隱式獲得釋放鎖
2. ReentrantLock 可回應中斷、可輪回,synchronized 是不可以回應中斷的,為處理鎖的
不可用性提供了更高的靈活性
3. ReentrantLock 是 API 級別的,synchronized 是 JVM 級別的
4. ReentrantLock 可以實作公平鎖
5. ReentrantLock 通過 Condition 可以系結多個條件
6. 底層實作不一樣, synchronized 是同步阻塞,使用的是悲觀并發策略,lock 是同步非阻
塞,采用的是樂觀并發策略
7. Lock 是一個介面,而 synchronized 是 Java 中的關鍵字,synchronized 是內置的語言
實作,
8. synchronized 在發生例外時,會自動釋放執行緒占有的鎖,因此不會導致死鎖現象發生;
而 Lock 在發生例外時,如果沒有主動通過 unLock()去釋放鎖,則很可能造成死鎖現象,
因此使用 Lock 時需要在 finally 塊中釋放鎖,
9. Lock 可以讓等待鎖的執行緒回應中斷,而 synchronized 卻不行,使用 synchronized 時,
等待的執行緒會一直等待下去,不能夠回應中斷,
10. 通過 Lock 可以知道有沒有成功獲取鎖,而 synchronized 卻無法辦到,
11. Lock 可以提高多個執行緒進行讀操作的效率,既就是實作讀寫鎖等

六、CAS無鎖技術(簡單了解即可,參考https://blog.csdn.net/ls5718/article/details/52563959)

七、volatile關鍵字的作用和原理(參考https://blog.csdn.net/zezezuiaiya/article/details/81456060)

被volatile關鍵字修飾的變數,編譯器與運行時都會注意到這個變數是共享的,因此不會將該變數上的操作與其他記憶體操作一起重排序,volatile變數不會被快取在暫存器或者對其他處理器不可見的地方,因此在讀取volatile型別的變數時總會回傳最新寫入的值,

在訪問volatile變數時不會執行加鎖操作,因此也就不會使執行執行緒阻塞,因此volatile變數是一種比sychronized關鍵字更輕量級的同步機制,當對非 volatile 變數進行讀寫的時候,每個執行緒先從記憶體拷貝變數到CPU快取中,如果計算機有多個CPU,每個執行緒可能在不同的CPU上被處理,這意味著每個執行緒可以拷貝到不同的 CPU cache 中,而宣告變數是 volatile 的,JVM 保證了每次讀變數都從記憶體中讀,跳過 CPU cache 這一步,

可見性是指當多個執行緒訪問同一個變數時,一個執行緒修改了這個變數的值,其他執行緒能夠立即看得到修改的值,Java中的volatile關鍵字提供了一個功能,那就是被其修飾的變數在被修改后可以立即同步到主記憶體,被其修飾的變數在每次是用之前都從主記憶體重繪,因此,可以使用volatile來保證多執行緒操作時變數的可見性,

volatile不具備原子性,但是擁有可見性,并且在一定程度上擁有有序性,

八、ThreadLocal和ThreadPoolExectutor

ThreadLocal叫做執行緒變數,意思是ThreadLocal中填充的變數屬于當前執行緒,該變數對其他執行緒而言是隔離的,ThreadLocal為變數在每個執行緒中都創建了一個副本,那么每個執行緒可以訪問自己內部的副本變數,

使用場景

  1. 在進行物件跨層傳遞的時候,使用ThreadLocal可以避免多次傳遞,打破層次間的約束,
  2. 執行緒間資料隔離
  3. 進行事務操作,用于存盤執行緒事務資訊,
  4. 資料庫連接,Session會話管理,

ThreadPoolExectutor(需要完善)

九、常見執行緒池

Java通過Executors提供四種執行緒池,分別為:
newCachedThreadPool創建一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閑執行緒,若無可回收,則新建執行緒,
newFixedThreadPool 創建一個定長執行緒池,可控制執行緒最大并發數,超出的執行緒會在佇列中等待,
newScheduledThreadPool 創建一個定長執行緒池,支持定時及周期性任務執行,
newSingleThreadExecutor 創建一個單執行緒化的執行緒池,它只會用唯一的作業執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先級)執行,

十、分布式環境下如何保證執行緒安全

避免并發

在分布式環境中,如果存在并發問題,那么很難通過技術去解決,或者解決的代價很大,所以我們首先要想想是不是可以通過某些策略和業務設計來避免并發,比如通過合理的時間調度,避開共享資源的存取沖突,另外,在并行任務設計上可以通過適當的策略,保證任務與任務之間不存在共享資源,比如在以前博文中提到的例子,我們需要用多執行緒或分布式集群來計算一堆客戶的相關統計值,由于客戶的統計值是共享資料,因此會有并發潛在可能,但從業務上我們可以分析出客戶與客戶之間 資料是不共享的,因此可以設計一個規則來保證一個客戶的計算作業和資料訪問只會被一個執行緒或一臺作業機完成,而不是把一個客戶的計算作業分配給多個執行緒去 完成,這種規則很容易設計,例如可以采用hash演算法,

時間戳

分布式環境中并發是沒法保證時序的,無論是通過遠程介面的同步呼叫或異步訊息,因此很容易造成某些對時序性有要求的業務在高并發時產生錯誤,比如系統A需要把某個值的變更同步到系統B,由于通知的時序問題會導致一個過期的值覆寫了有效值,對于這個問題,常用的辦法就是采用時間戳的方式,每次系統A發送變更給系統B的時候需要帶上一個能標示時序的時間戳,系統B接到通知后會拿時間戳與存在的時間戳比較,只有當通知的時間戳大于存在的時間戳,才做更新,這種方式比較簡單,但關鍵在于呼叫方一般要保證時間戳的時序有效性,

串行化

有的時候可以通過串行化可能產生并發問題操作,犧牲性能和擴展性,來滿足對資料一致性的要求,比如分布式訊息系統就沒法保證訊息的有序性,但可以通過變分布式訊息系統為單一系統就可以保證訊息的有序性了,另外,當接收方沒法處理呼叫有序性,可以通過一個佇列先把呼叫資訊快取起來,然后再串行地處理這些呼叫,

資料庫

分布式環境中的共享資源不能通過Java里同步方法或加鎖來保證執行緒安全,但資料庫是分布式各服務器的共享點,可以通過資料庫的高可靠一致性機制來滿足需求,比如,可以通過唯一性索引來解決并發程序中重復資料的生產或重復任務的執行;另外有些更新計算操作也盡量通過sql來完成,因為在程式段計算好后再去更新就有可能發生臟復寫問題,但通過一條sql來完成計算和更新就可以通過資料庫的鎖機制來保證update操作的一致性,

行鎖

有的事務比較復雜,無法通過一條sql解決問題,并且有存在并發問題,這時就需要通過行鎖來解決,一般行鎖可以通過以下方式來實作:
對于Oracle資料庫,可以采用select ... for update方式,這種方式會有潛在的危險,就是如果沒有commit就會造成這行資料被鎖住,其他有涉及到這行資料的任務都會被掛起,應該謹慎使用
在表里添加一個標示鎖的欄位,每次操作前,先通過update這個鎖欄位來完成類似競爭鎖的操作,操作完成后在update鎖欄位復位,標示已歸還鎖,這種方式比較安全,不好的地方在于這些update鎖欄位的操作就是額外的性能消耗

統一觸發途徑

當一個資料可能會被多個觸發點或多個業務涉及到,就有并發問題產生的隱患,因此可以通過前期架構和業務設計,盡量統一觸發途徑,觸發途徑少了一是減少并發的可能,也有利于對于并發問題的分析和判斷,

如何保證高并發時執行緒安全?

對于商城一類系統中,單點登錄、購物車、訂單這些都有并發,

用AtomicInteger、synchronized、Lock、ThreadLocal等類來保證在代碼層面上的執行緒安全;如果是功能上需要自主多執行緒處理,那么也會使用線程池ThreadPool來提高并發效率,

對高并發的處理會使用Redis的分布式鎖(setnx),將對于服務器的承載力達到一定數量后,之后的請求全部加入佇列處理,

負載均衡:在代碼層級上對不同的業務進行讀寫分離;而資料庫上進行集群和主從復制,在應用服務器上對應的對每個服務器都運用lvs+keepalive模式進行服務器集群;如果硬體資源足夠的話那么可以對集群節點更加多和更加分散提高并發能力和系統穩定性,

Redis是一個開源,先進的key-value存盤,并用于構建高性能,可擴展的Web應用程式的完美解決方案,是執行緒安全的,
Redis三個主要特點:
  Redis資料庫完全在記憶體中,使用磁盤僅用于持久性,
  相比許多鍵值資料存盤,Redis擁有一套較為豐富的資料型別(list,string,sort,set,hash),
  Redis可以將資料復制到任意數量的從服務器,

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/260394.html

標籤:其他

上一篇:Redis集群原理詳解

下一篇:Chain of Responsibility 職責鏈模式

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 面試突擊第一季,第二季,第三季

    第一季必考 https://www.bilibili.com/video/BV1FE411y79Y?from=search&seid=15921726601957489746 第二季分布式 https://www.bilibili.com/video/BV13f4y127ee/?spm_id_fro ......

    uj5u.com 2020-09-10 05:35:24 more
  • 第三單元作業總結

    1.前言 這應該是本學期最后一次寫作業總結了吧。總體來說,對作業的節奏也差不多掌握了,作業做起來的效率也更高了。雖然和之前的作業一樣,作業中都要用到新的知識,但是相比之前,更加懂得了如何利用工具以及資料。雖然之間卡過殼,但總體而言,這幾次作業還算完成的比較好。 2.作業程序總結 相比前兩個單元,此單 ......

    uj5u.com 2020-09-10 05:35:41 more
  • 北航OO(2020)第四單元博客作業暨課程總結博客

    北航OO(2020)第四單元博客作業暨課程總結博客 本單元作業的架構設計 在本單元中,由于UML圖具有比較清晰的樹形結構,因此我對其中需要進行查詢操作的元素進行了包裝,在樹的父節點中存盤所有孩子的參考。考慮到性能問題,我采用了快取機制,一次查詢后盡可能快取已經遍歷過的資訊,以減少遍歷次數。 本單元我 ......

    uj5u.com 2020-09-10 05:35:48 more
  • BUAA_OO_第四單元

    一、UML決議器設計 ? 先看下題目:第四單元實作一個基于JDK 8帶有效性檢查的UML(Unified Modeling Language)類圖,順序圖,狀態圖分析器 MyUmlInteraction,實際上我們要建立一個有向圖模型,UML中的物件(元素)可能與同級元素連接,也可與低級元素相連形成 ......

    uj5u.com 2020-09-10 05:35:54 more
  • 6.1邏輯運算子

    邏輯運算子 1. && 短路與 運算式1 && 運算式2 01.運算式1為true并且運算式2也為true 整體回傳為true 02.運算式1為false,將不會執行運算式2 整體回傳為false 03.只要有一個運算式為false 整體回傳為false 2. || 短路或 運算式1 || 運算式2 ......

    uj5u.com 2020-09-10 05:35:56 more
  • BUAAOO 第四單元 & 課程總結

    1. 第四單元:StarUml檔案決議 本單元采用了圖模型決議UML。 UML檔案可以抽象為圖、子圖、邊的邏輯結構。 在實作中,圖的節點包括類、介面、屬性,子圖包括狀態圖、順序圖等。 采用了三次遍歷UML元素的方法建圖,第一遍遍歷建點,第二、三次遍歷設定屬性、連邊,實作圖物件的初始化。這里借鑒了一些 ......

    uj5u.com 2020-09-10 05:36:06 more
  • 談談我對C# 多型的理解

    面向物件三要素:封裝、繼承、多型。 封裝和繼承,這兩個比較好理解,但要理解多型的話,可就稍微有點難度了。今天,我們就來講講多型的理解。 我們應該經常會看到面試題目:請談談對多型的理解。 其實呢,多型非常簡單,就一句話:呼叫同一種方法產生了不同的結果。 具體實作方式有三種。 一、多載 多載很簡單。 p ......

    uj5u.com 2020-09-10 05:36:09 more
  • Python 資料驅動工具:DDT

    背景 python 的unittest 沒有自帶資料驅動功能。 所以如果使用unittest,同時又想使用資料驅動,那么就可以使用DDT來完成。 DDT是 “Data-Driven Tests”的縮寫。 資料:http://ddt.readthedocs.io/en/latest/ 使用方法 dd. ......

    uj5u.com 2020-09-10 05:36:13 more
  • Python里面的xlrd模塊詳解

    那我就一下面積個問題對xlrd模塊進行學習一下: 1.什么是xlrd模塊? 2.為什么使用xlrd模塊? 3.怎樣使用xlrd模塊? 1.什么是xlrd模塊? ?python操作excel主要用到xlrd和xlwt這兩個庫,即xlrd是讀excel,xlwt是寫excel的庫。 今天就先來說一下xl ......

    uj5u.com 2020-09-10 05:36:28 more
  • 當我們創建HashMap時,底層到底做了什么?

    jdk1.7中的底層實作程序(底層基于陣列+鏈表) 在我們new HashMap()時,底層創建了默認長度為16的一維陣列Entry[ ] table。當我們呼叫map.put(key1,value1)方法向HashMap里添加資料的時候: 首先,呼叫key1所在類的hashCode()計算key1 ......

    uj5u.com 2020-09-10 05:36:38 more
最新发布
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:20:47 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:20:25 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:20:17 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:20:10 more
  • 【中介者設計模式詳解】C/Java/JS/Go/Python/TS不同語言實作

    * 中介者模式是一種行為型設計模式,它可以用來減少類之間的直接依賴關系,
    * 將物件之間的通信封裝到一個中介者物件中,從而使得各個物件之間的關系更加松散。
    * 在中介者模式中,物件之間不再直接相互互動,而是通過中介者來中轉訊息。 ......

    uj5u.com 2023-04-20 08:19:44 more
  • 露天煤礦現場調研和交流案例分享

    他們集團的資訊化公司及研究院在一個礦區正在做智能礦山的統一平臺的 試點,專案投資大概1億,包括了礦山的各方面的內容,顯示得我們這次交流有點多余。他們2年前開始做智能礦山的規劃,有很多煤礦行業專家的加持,他們的描述是非常完美,但是去年底應該上線的平臺,現在還沒有看到影子。他們確實有很多場景需求,但是被... ......

    uj5u.com 2023-04-20 08:19:07 more
  • 《社區人員管理》實戰案例設計&個人案例分享

    設計是一個讓人夢想成真程序,開始編碼、測驗、除錯之前進行需求分析和架構設計,才能保證關鍵方面都做正確 ......

    uj5u.com 2023-04-20 08:18:57 more
  • 軟體架構生態化-多角色交付的探索實踐

    作為一個技術架構師,不僅僅要緊跟行業技術趨勢,還要結合研發團隊現狀及痛點,探索新的交付方案。在日常中,你是否遇到如下問題 “ 業務需求排期長研發是瓶頸;非研發角色感受不到研發技改提效的變化;引入ISV 團隊又擔心質量和安全,培訓周期長“等等,基于此我們探索了一種新的技術體系及交付方案來解決如上問題。 ......

    uj5u.com 2023-04-20 08:18:49 more
  • 05單件模式

    #經典的單件模式 public class Singleton { private static Singleton uniqueInstance; //一個靜態變數持有Singleton類的唯一實體。 // 其他有用的實體變數寫在這里 //構造器宣告為私有,只有Singleton可以實體化這個類! ......

    uj5u.com 2023-04-19 08:42:51 more
  • 【架構與設計】常見微服務分層架構的區別和落地實踐

    軟體工程的方方面面都遵循一個最基本的道理:沒有銀彈,架構分層模型更是如此,每一種都有各自優缺點,所以請根據不同的業務場景,并遵循簡單、可演進這兩個重要的架構原則選擇合適的架構分層模型即可。 ......

    uj5u.com 2023-04-19 08:42:41 more