Java常用類庫(kù)中(ThreadLocal、Comparable比較器、AutoCloseable、Optional空處理)

1.ThreadLocal線程獨(dú)立
如果說(shuō)每一個(gè)用戶代表一個(gè)線程,那么當(dāng)用戶去訪問(wèn)自己的獨(dú)有的比如id時(shí)候就應(yīng)該正確返回自己的id。ThreadLocal就好比一個(gè)大儲(chǔ)物柜里面有許多小的儲(chǔ)物柜,每一個(gè)線程擁有自己的儲(chǔ)物柜,方便自己拿取自己的東西,這樣就能保證數(shù)據(jù)之間的獨(dú)立與安全
ThreadLocal類常用的方法:
T get()
返回當(dāng)前線程關(guān)聯(lián)的變量副本的值。如果沒(méi)有設(shè)置過(guò),則返回null
。void set(T value)
將當(dāng)前線程關(guān)聯(lián)的變量副本設(shè)置為指定的值。void remove()
刪除當(dāng)前線程關(guān)聯(lián)的變量副本。protected T initialValue()
提供一個(gè)初始化值,用于首次訪問(wèn)時(shí)創(chuàng)建變量副本的情況。子類可以重寫此方法來(lái)指定自定義的初始化值。static <S> ThreadLocal<S> withInitial(Supplier<? extends S> supplier)
創(chuàng)建一個(gè)帶有初始值提供者的ThreadLocal
實(shí)例。每個(gè)線程在首次訪問(wèn)時(shí),都會(huì)使用提供者生成一個(gè)初始值。static ThreadLocalRandom current()
返回當(dāng)前線程關(guān)聯(lián)的ThreadLocalRandom
實(shí)例
案例要求:
設(shè)置三個(gè)線程ABC每一個(gè)線程要有獨(dú)立的資源。并且每個(gè)線程輸出自己獨(dú)立的資源

?為什么要用private static final ThreadLocal<Message> ThreadLocal = new ThreadLocal<Message>();static final修飾為了什么目的?
在這段代碼中,使用
private static final ThreadLocal<Message> ThreadLocal = new ThreadLocal<Message>();
將ThreadLocal
聲明為私有靜態(tài)常量。
private
修飾符表示ThreadLocal
只能在Channel
類內(nèi)部訪問(wèn),禁止外部直接訪問(wèn),從而保證了對(duì)ThreadLocal
的訪問(wèn)權(quán)限的封裝性。
static
修飾符表示ThreadLocal
是一個(gè)類級(jí)別的變量,而不是實(shí)例級(jí)別的變量。這意味著所有的Channel
實(shí)例共享同一個(gè)ThreadLocal
對(duì)象,而不是每個(gè)實(shí)例都擁有自己的副本。這樣做的目的是為了確保線程間的隔離效果。
final
修飾符表示ThreadLocal
引用的對(duì)象是不可變的,一旦引用被賦值,就無(wú)法再更改其指向的對(duì)象。這里將ThreadLocal
聲明為常量是為了防止意外修改ThreadLocal
的引用,確保程序的穩(wěn)定性和可靠性。總的來(lái)說(shuō),將
ThreadLocal
聲明為private static final
的目的是為了實(shí)現(xiàn)線程間的資源隔離并確保其訪問(wèn)權(quán)限的封裝、共享和穩(wěn)定性。
面試題:ThreadLocal 是什么?有哪些使用場(chǎng)景?
ThreadLocal 是一個(gè)本地線程副本變量工具類,在每個(gè)線程中都創(chuàng)建了一個(gè) ThreadLocalMap 對(duì)象,簡(jiǎn)單說(shuō) ThreadLocal 就是一種以空間換時(shí)間的做法,每個(gè)線程可以訪問(wèn)自己內(nèi)部 ThreadLocalMap 對(duì)象內(nèi)的 value。通過(guò)這種方式,避免資源在多線程間共享。
原理:線程局部變量是局限于線程內(nèi)部的變量,屬于線程自身所有,不在多個(gè)線程間共享。Java提供ThreadLocal類來(lái)支持線程局部變量,是一種實(shí)現(xiàn)線程安全的方式。但是在管理環(huán)境下(如 web 服務(wù)器)使用線程局部變量的時(shí)候要特別小心,在這種情況下,工作線程的生命周期比任何應(yīng)用變量的生命周期都要長(zhǎng)。任何線程局部變量一旦在工作完成后沒(méi)有釋放,Java 應(yīng)用就存在內(nèi)存泄露的風(fēng)險(xiǎn)。
經(jīng)典的使用場(chǎng)景是為每個(gè)線程分配一個(gè) JDBC 連接 Connection。這樣就可以保證每個(gè)線程的都在各自的 Connection 上進(jìn)行數(shù)據(jù)庫(kù)的操作,不會(huì)出現(xiàn) A 線程關(guān)了 B線程正在使用的 Connection; 還有 Session 管理 等問(wèn)題。
?面試題:請(qǐng)談?wù)?ThreadLocal 是怎么解決并發(fā)安全的?
在java程序中,常用的有兩種機(jī)制來(lái)解決多線程并發(fā)問(wèn)題,一種是sychronized方式,通過(guò)鎖機(jī)制,一個(gè)線程執(zhí)行時(shí),讓另一個(gè)線程等待,是以時(shí)間換空間的方式來(lái)讓多線程串行執(zhí)行。而另外一種方式就是ThreadLocal方式,通過(guò)創(chuàng)建線程局部變量,以空間換時(shí)間的方式來(lái)讓多線程并行執(zhí)行。兩種方式各有優(yōu)劣,適用于不同的場(chǎng)景,要根據(jù)不同的業(yè)務(wù)場(chǎng)景來(lái)進(jìn)行選擇。
在spring的源碼中,就使用了ThreadLocal來(lái)管理連接,在很多開(kāi)源項(xiàng)目中,都經(jīng)常使用ThreadLocal來(lái)控制多線程并發(fā)問(wèn)題,因?yàn)樗銐虻暮?jiǎn)單,我們不需要關(guān)心是否有線程安全問(wèn)題,因?yàn)樽兞渴敲總€(gè)線程所特有的。
面試題:?很多人都說(shuō)要慎用 ThreadLocal,談?wù)勀愕睦斫猓褂?ThreadLocal 需要注意些什么?
ThreadLocal 變量解決了多線程環(huán)境下單個(gè)線程中變量的共享問(wèn)題,使用名為ThreadLocalMap的哈希表進(jìn)行維護(hù)(key為ThreadLocal變量名,value為ThreadLocal變量的值);
使用時(shí)需要注意以下幾點(diǎn):
線程之間的threadLocal變量是互不影響的,
使用private final static進(jìn)行修飾,防止多實(shí)例時(shí)內(nèi)存的泄露問(wèn)題
線程池環(huán)境下使用后將threadLocal變量remove掉或設(shè)置成一個(gè)初始值

2.Comparable比較器與Comparetor
在現(xiàn)實(shí)生活中一個(gè)班級(jí)有很多個(gè)人數(shù),也就意味著有許多個(gè)對(duì)象,如果經(jīng)歷一次考試之后我需要對(duì)考試后大家對(duì)象數(shù)組進(jìn)行排序,需要成績(jī)從高到低排序,比如黃小龍 成績(jī)總分60 ,藍(lán)小龍 成績(jī)總分50,綠小龍 成績(jī)總分 40等等,可以通過(guò)Comparable比較器去設(shè)置比較再進(jìn)行排序
Comparable接口常用的方法
方法描述
int compareTo(T other)
將當(dāng)前對(duì)象與另一個(gè)對(duì)象進(jìn)行比較。返回一個(gè)負(fù)整數(shù)、零或正整數(shù),表示當(dāng)前對(duì)象小于、等于或大于另一個(gè)對(duì)象。boolean equals(Object obj)
檢查當(dāng)前對(duì)象是否與另一個(gè)對(duì)象相等。default Comparator<T> reversed()
返回當(dāng)前比較器的逆序(降序)比較器。默認(rèn)方法,可以在實(shí)現(xiàn)Comparable
接口的類中使用。default Comparator<T> thenComparing(...)
返回一個(gè)比較器,該比較器首先使用當(dāng)前比較器進(jìn)行比較,然后使用其他指定的比較器進(jìn)行進(jìn)一步比較。默認(rèn)方法,可以在實(shí)現(xiàn)Comparable
接口的類中使用。
注意:
實(shí)現(xiàn)接口需要覆寫CompareTo方法,該方法有三個(gè)返回值
return? 1 -->表示結(jié)果大于
return -1-->表示結(jié)果小于
return? 0 -->表示結(jié)果相等
案例要求:經(jīng)歷一場(chǎng)考試后,班級(jí)需要對(duì)考試班里的同學(xué)排名的張貼告示,要求成績(jī)從高到底,每個(gè)對(duì)象需要有以下信息:名字,學(xué)號(hào),成績(jī)總分。以下是本次班級(jí)考試結(jié)果
張三,210101,560
李四 ,? 210108, ? 589
王五 ,? 210116,?? 340
趙六,?? 210153, ? 623
請(qǐng)用數(shù)組對(duì)象輸出成績(jī)從高到低
案例代碼:

?注意:Arrays類中引用了Comparable的比較方法CompareTo才能用sort方法

3.AutoCloseable接口
由于資源是有限的,隨著程序的擴(kuò)大對(duì)資源越來(lái)越多的需求,資源會(huì)越來(lái)越緊張,所以為了保證資源的合理使用,一些資源使用后就不太需要的時(shí)候,就需要進(jìn)行釋放所以引入接口AutoCloseable進(jìn)行自動(dòng)的資源釋放
AutoCloseable接口的常用方法:
方法描述
void close() throws Exception
關(guān)閉資源的方法,需要在實(shí)現(xiàn)類中實(shí)現(xiàn)。使用完資源后,應(yīng)該調(diào)用該方法來(lái)釋放資源。注意,close()
方法可能會(huì)拋出異常,因此在調(diào)用時(shí)應(yīng)該進(jìn)行異常處理。default void addSuppressed(Throwable exception)
將一個(gè)異常附加到當(dāng)前正在關(guān)閉的異常上。在關(guān)閉資源時(shí),如果出現(xiàn)了其他異常,可以通過(guò)該方法將其添加到關(guān)閉資源的異常中,以便于統(tǒng)一處理。default void suppressedExceptions(Throwable... exceptions)
抑制指定的一組異常。在關(guān)閉資源時(shí),如果出現(xiàn)了多個(gè)異常,可以通過(guò)該方法將它們?nèi)恳种破饋?lái)。
?案例要求與案例代碼:

注意:
要實(shí)現(xiàn)自動(dòng)執(zhí)行
close()
方法,可以使用try-with-resources
語(yǔ)句塊,它會(huì)在代碼塊結(jié)束后自動(dòng)調(diào)用資源的close()
方法來(lái)釋放資源。

4.(重點(diǎn)掌握)Optional空處理
在引用對(duì)象中存在Null,但是如果調(diào)用一個(gè)類的靜態(tài)方法,該方法實(shí)現(xiàn)需要一個(gè)實(shí)例化對(duì)象的值,那么此時(shí)會(huì)出現(xiàn)空異常(NullPointerException)
舉個(gè)例子
為此Java提供Optional空處理來(lái)減少空指針異常的情況
以下是Optional的常用方法
方法描述
of(T value)
創(chuàng)建一個(gè)包含指定非空值的Optional
對(duì)象ofNullable(T value)
創(chuàng)建一個(gè)包含指定值的Optional
對(duì)象,如果值為空,則創(chuàng)建包含空值的Optional
對(duì)象empty()
創(chuàng)建一個(gè)空的Optional
對(duì)象isPresent()
判斷Optional
對(duì)象是否包含非空值get()
獲取Optional
對(duì)象中的非空值orElse(T other)
如果Optional
對(duì)象中存在非空值,則返回該值;否則返回指定的默認(rèn)值orElseGet(Supplier<? extends T> otherSupplier)
如果Optional
對(duì)象中存在非空值,則返回該值;否則通過(guò)Supplier
提供的方法生成并返回默認(rèn)值orElseThrow(Supplier<? extends X> exceptionSupplier)
如果Optional
對(duì)象中存在非空值,則返回該值;否則根據(jù)Supplier
提供的方法拋出異常ifPresent(Consumer<? super T> consumer)
如果Optional
對(duì)象中存在非空值,則對(duì)該值執(zhí)行指定操作filter(Predicate<? super T> predicate)
如果Optional
對(duì)象中存在非空值,并且滿足指定條件,則返回當(dāng)前對(duì)象;否則返回空的Optional
對(duì)象map(Function<? super T,? extends U> mapper)
如果Optional
對(duì)象中存在非空值,則對(duì)該值應(yīng)用指定的映射函數(shù),并返回包含映射結(jié)果的Optional
對(duì)象flatMap(Function<? super T,Optional<U>> mapper)
如果Optional
對(duì)象中存在非空值,則對(duì)該值應(yīng)用指定的映射函數(shù),并返回映射結(jié)果的Optional
對(duì)象;否則返回空的Optional
對(duì)象
?案例代碼:
