Future cancel迷惑性boolean入?yún)⒔馕?/h1>
更新時(shí)間:2023年02月28日 16:49:13 作者:Code皮皮蝦
這篇文章主要為大家介紹了Future cancel迷惑性boolean入?yún)⒔馕觯行枰呐笥芽梢越梃b參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
前言
當(dāng)我們使用線程池submit一個(gè)任務(wù)后,會(huì)返回一個(gè)Future,而在Future接口中存在一個(gè)cancel方法,來(lái)幫助我們?nèi)∠羧蝿?wù)。
但是cancel方法有一個(gè)boolean類(lèi)型的入?yún)?,比較迷惑,之前也了解過(guò)該入?yún)?code>true 和 false的區(qū)別,但過(guò)一段時(shí)間之后就又忘了,遂寫(xiě)了本文進(jìn)行記錄,順便了解下源碼~
/**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when {@code cancel} is called,
* this task should never run. If the task has already started,
* then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return {@code true}. Subsequent calls to {@link #isCancelled}
* will always return {@code true} if this method returned {@code true}.
*
* @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
* {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
上面是cancel方法的接口定義,當(dāng)然英文看著麻煩,咱直接翻譯成看得懂的~
cancel方法,會(huì)嘗試取消任務(wù)的執(zhí)行,但如果任務(wù)已經(jīng)完成、已經(jīng)取消或其他原因無(wú)法取消,則嘗試取消任務(wù)失敗。
如果取消成功,并且在取消時(shí)
- 該任務(wù)還未執(zhí)行,那么這個(gè)任務(wù)永遠(yuǎn)不會(huì)執(zhí)行。
- 如果該任務(wù)已經(jīng)啟動(dòng),那么會(huì)根據(jù)
cancel的boolean入?yún)?lái)決定是否中斷執(zhí)行此任務(wù)的線程來(lái)停止任務(wù)。
通過(guò)注釋我們大致能了解到cancel的一個(gè)作用,但是還不夠細(xì)致,接下來(lái)我們通過(guò)源碼解讀詳細(xì)的帶大家了解一下~
FutureTask任務(wù)狀態(tài)認(rèn)知
首先,我們先了解下FutureTask中對(duì)任務(wù)狀態(tài)的定義
在使用線程池submit后,實(shí)際上是返回的一個(gè)FutureTask,而FutureTask中對(duì)于任務(wù)定義了以下?tīng)顟B(tài),并且在注釋中,也定義了狀態(tài)的流轉(zhuǎn)過(guò)程~
/**
* Possible state transitions:
* NEW -> COMPLETING -> NORMAL
* NEW -> COMPLETING -> EXCEPTIONAL
* NEW -> CANCELLED
* NEW -> INTERRUPTING -> INTERRUPTED
*/
private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
但是通過(guò)對(duì)上面狀態(tài)定義的了解,我們可以發(fā)現(xiàn),在FutureTask中并沒(méi)有一個(gè)表明任務(wù)處于執(zhí)行中的一個(gè)狀態(tài)!
直接看FutureTask的run方法源碼
public void run() {
if (state != NEW ||
!RUNNER.compareAndSet(this, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
// 執(zhí)行任務(wù)
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
// 執(zhí)行異常
setException(ex);
}
if (ran)
// 正常執(zhí)行完畢
set(result);
}
} finally {
//... 省略
}
}
?
protected void setException(Throwable t) {
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
outcome = t;
STATE.setRelease(this, EXCEPTIONAL); // final state
finishCompletion();
}
}
?
protected void set(V v) {
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
outcome = v;
STATE.setRelease(this, NORMAL); // final state
finishCompletion();
}
}
通過(guò)上面源碼,我們也能了解到
- 當(dāng)任務(wù)正常執(zhí)行完畢時(shí),任務(wù)狀態(tài)流轉(zhuǎn):
NEW -> COMPLETING -> NORMAL - 任務(wù)執(zhí)行異常時(shí),任務(wù)狀態(tài)流轉(zhuǎn):
NEW -> COMPLETING -> EXCEPTIONAL
所以,當(dāng)任務(wù)剛創(chuàng)建,或者是任務(wù)在執(zhí)行過(guò)程中,任務(wù)的狀態(tài)都是NEW
cancel源碼分析
此時(shí)再來(lái)分析cancel源碼
public boolean cancel(boolean mayInterruptIfRunning) {
// NEW為新建或者運(yùn)行態(tài)
// 1. 此時(shí)任務(wù)已經(jīng)不是NEW,說(shuō)明要么是完成要么是異常,取消不了,所以返回false
// 2. 此時(shí)任務(wù)還是NEW,如果我們傳入true,則CAS標(biāo)記任務(wù)為INTERRUPTING,否則是CANCELLED
// 防止并發(fā)取消任務(wù),CAS只會(huì)有一個(gè)線程成功,其余線程失敗
if (!(state == NEW && STATE.compareAndSet
(this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try {
// 傳入true,則打斷該任務(wù)的執(zhí)行線程
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally {
// 比較任務(wù)狀態(tài)為INTERRUPTED
STATE.setRelease(this, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
通過(guò)對(duì)FutureTask任務(wù)狀態(tài)的認(rèn)知,再結(jié)合對(duì)cancel源碼的分析
我們可以總結(jié)出以下結(jié)論
當(dāng)任務(wù)已經(jīng)完成或者異常時(shí),無(wú)法取消任務(wù)
任務(wù)處于新建或者運(yùn)行狀態(tài)時(shí)
cancel方法入?yún)魅?code>true
將任務(wù)狀態(tài)NEW -> INTERRUPTING -> INTERRUPTED,并打斷執(zhí)行該任務(wù)的線程
cancel方法入?yún)魅?code>false
將任務(wù)狀態(tài)NEW -> CANCELLED
但有個(gè)問(wèn)題,傳入false只是將狀態(tài)從NEW變成CANCELLED嘛,這好像沒(méi)啥用?。?/p>
當(dāng)然不是,此時(shí)我們需要再回頭看看FutureTask的run方法
public void run() {
if (state != NEW ||
!RUNNER.compareAndSet(this, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
// 執(zhí)行異常
setException(ex);
}
if (ran)
// 正常執(zhí)行完畢
set(result);
}
} finally {
//... 省略
}
}
run方法開(kāi)頭我們可以看到,如果任務(wù)的狀態(tài)不是NEW,那么會(huì)直接return,不執(zhí)行任務(wù)
那此時(shí)再想想傳入false將任務(wù)狀態(tài)從NEW -> CANCELLED,是不是當(dāng)任務(wù)還沒(méi)有開(kāi)始執(zhí)行時(shí),我們cancel(false)就可以取消掉未執(zhí)行的任務(wù)了~
總結(jié)
通過(guò)上面的源碼解讀,我們大致能了解了cancel的機(jī)制,但是我們還是完善的總結(jié)一下
任務(wù)如果不是NEW狀態(tài)是不會(huì)執(zhí)行的
cancel取消任務(wù)會(huì)改變?nèi)蝿?wù)的狀態(tài)
- 如果傳入
true, 則將任務(wù)狀態(tài)NEW -> INTERRUPTING -> INTERRUPTED,并打斷執(zhí)行該任務(wù)的線程 - 如果傳入
false,將任務(wù)狀態(tài)NEW -> CANCELLED
傳入false只能取消還未執(zhí)行的任務(wù)
傳入true,能取消未執(zhí)行的任務(wù),能打斷正在執(zhí)行的任務(wù)
擴(kuò)展知識(shí)點(diǎn)
在cancel源碼中,我們可以看到finally中會(huì)去調(diào)用finishCompletion
那么,finishCompletion是干啥的呢?
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
// 原子性將WAITERS設(shè)置為null
if (WAITERS.weakCompareAndSet(this, q, null)) {
// 遍歷WAITERS,將阻塞的線程都喚醒
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null;
q = next;
}
break;
}
}
?
// 擴(kuò)展方法,交給自己實(shí)現(xiàn)
done();
?
callable = null;
}
大家可以想想,當(dāng)我們submit一個(gè)任務(wù)時(shí),一般情況下都會(huì)需要去獲取他的返回值,會(huì)調(diào)用get方法進(jìn)行阻塞獲取
在FutureTask中,會(huì)維護(hù)一條鏈表,該鏈表記錄了等待獲取該任務(wù)返回值被阻塞的線程
在調(diào)用get方法時(shí),會(huì)將組裝waiters鏈表

所以,當(dāng)我們?nèi)∠粋€(gè)任務(wù)時(shí),是不是也應(yīng)該去將阻塞等待獲取該任務(wù)的所有線程進(jìn)行喚醒,而finishCompletion方法就是做這個(gè)事情的~
以上就是Future cancel迷惑性boolean入?yún)⒔馕龅脑敿?xì)內(nèi)容,更多關(guān)于Future cancel boolean入?yún)⒌馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
-
Java 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能簡(jiǎn)單實(shí)例
這篇文章主要介紹了Java 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下 2017-04-04
-
SpringBoot RestTemplate請(qǐng)求日志打印方式
這篇文章主要介紹了SpringBoot RestTemplate請(qǐng)求日志打印方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2023-07-07
-
Java接口和抽象類(lèi)實(shí)現(xiàn)抽象和多態(tài)的方法示例
接口和抽象類(lèi)是 Java 中兩種實(shí)現(xiàn)抽象和多態(tài)的方法。它們之間有一些區(qū)別,但也有一些相似之處。這一節(jié)我們將通過(guò)詳細(xì)的例子來(lái)更深入地了解接口和抽象類(lèi) 2023-05-05
-
詳解Java使用Pipeline對(duì)Redis批量讀寫(xiě)(hmset&hgetall)
本篇文章主要介紹了Java使用Pipeline對(duì)Redis批量讀寫(xiě)(hmset&hgetall),具有一定的參考價(jià)值,有興趣的可以了解一下。
2016-12-12
-
Java 交換兩個(gè)變量的數(shù)值實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇Java 交換兩個(gè)變量的數(shù)值實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧 2016-07-07
-
實(shí)例講解Java的設(shè)計(jì)模式編程中責(zé)任鏈模式的運(yùn)用
這篇文章主要介紹了Java的設(shè)計(jì)模式編程中責(zé)任鏈模式的運(yùn)用,講解了通過(guò)條件判斷結(jié)構(gòu)來(lái)分配不同對(duì)象的責(zé)任權(quán)限,需要的朋友可以參考下 2016-02-02
-
JPA-JpaRepository方法命名語(yǔ)法說(shuō)明
這篇文章主要介紹了JPA-JpaRepository方法命名語(yǔ)法說(shuō)明,具有很好的參考價(jià)值。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教 2021-11-11
-
淺談Java中幾種常見(jiàn)的比較器的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇淺談Java中幾種常見(jiàn)的比較器的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧 2017-10-10
最新評(píng)論
前言
當(dāng)我們使用線程池submit一個(gè)任務(wù)后,會(huì)返回一個(gè)Future,而在Future接口中存在一個(gè)cancel方法,來(lái)幫助我們?nèi)∠羧蝿?wù)。
但是cancel方法有一個(gè)boolean類(lèi)型的入?yún)?,比較迷惑,之前也了解過(guò)該入?yún)?code>true 和 false的區(qū)別,但過(guò)一段時(shí)間之后就又忘了,遂寫(xiě)了本文進(jìn)行記錄,順便了解下源碼~
/**
* Attempts to cancel execution of this task. This attempt will
* fail if the task has already completed, has already been cancelled,
* or could not be cancelled for some other reason. If successful,
* and this task has not started when {@code cancel} is called,
* this task should never run. If the task has already started,
* then the {@code mayInterruptIfRunning} parameter determines
* whether the thread executing this task should be interrupted in
* an attempt to stop the task.
*
* <p>After this method returns, subsequent calls to {@link #isDone} will
* always return {@code true}. Subsequent calls to {@link #isCancelled}
* will always return {@code true} if this method returned {@code true}.
*
* @param mayInterruptIfRunning {@code true} if the thread executing this
* task should be interrupted; otherwise, in-progress tasks are allowed
* to complete
* @return {@code false} if the task could not be cancelled,
* typically because it has already completed normally;
* {@code true} otherwise
*/
boolean cancel(boolean mayInterruptIfRunning);
上面是cancel方法的接口定義,當(dāng)然英文看著麻煩,咱直接翻譯成看得懂的~
cancel方法,會(huì)嘗試取消任務(wù)的執(zhí)行,但如果任務(wù)已經(jīng)完成、已經(jīng)取消或其他原因無(wú)法取消,則嘗試取消任務(wù)失敗。
如果取消成功,并且在取消時(shí)
- 該任務(wù)還未執(zhí)行,那么這個(gè)任務(wù)永遠(yuǎn)不會(huì)執(zhí)行。
- 如果該任務(wù)已經(jīng)啟動(dòng),那么會(huì)根據(jù)
cancel的boolean入?yún)?lái)決定是否中斷執(zhí)行此任務(wù)的線程來(lái)停止任務(wù)。
通過(guò)注釋我們大致能了解到cancel的一個(gè)作用,但是還不夠細(xì)致,接下來(lái)我們通過(guò)源碼解讀詳細(xì)的帶大家了解一下~
FutureTask任務(wù)狀態(tài)認(rèn)知
首先,我們先了解下FutureTask中對(duì)任務(wù)狀態(tài)的定義
在使用線程池submit后,實(shí)際上是返回的一個(gè)FutureTask,而FutureTask中對(duì)于任務(wù)定義了以下?tīng)顟B(tài),并且在注釋中,也定義了狀態(tài)的流轉(zhuǎn)過(guò)程~
/** * Possible state transitions: * NEW -> COMPLETING -> NORMAL * NEW -> COMPLETING -> EXCEPTIONAL * NEW -> CANCELLED * NEW -> INTERRUPTING -> INTERRUPTED */ private volatile int state; private static final int NEW = 0; private static final int COMPLETING = 1; private static final int NORMAL = 2; private static final int EXCEPTIONAL = 3; private static final int CANCELLED = 4; private static final int INTERRUPTING = 5; private static final int INTERRUPTED = 6;
但是通過(guò)對(duì)上面狀態(tài)定義的了解,我們可以發(fā)現(xiàn),在FutureTask中并沒(méi)有一個(gè)表明任務(wù)處于執(zhí)行中的一個(gè)狀態(tài)!
直接看FutureTask的run方法源碼
public void run() {
if (state != NEW ||
!RUNNER.compareAndSet(this, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
// 執(zhí)行任務(wù)
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
// 執(zhí)行異常
setException(ex);
}
if (ran)
// 正常執(zhí)行完畢
set(result);
}
} finally {
//... 省略
}
}
?
protected void setException(Throwable t) {
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
outcome = t;
STATE.setRelease(this, EXCEPTIONAL); // final state
finishCompletion();
}
}
?
protected void set(V v) {
if (STATE.compareAndSet(this, NEW, COMPLETING)) {
outcome = v;
STATE.setRelease(this, NORMAL); // final state
finishCompletion();
}
}
通過(guò)上面源碼,我們也能了解到
- 當(dāng)任務(wù)正常執(zhí)行完畢時(shí),任務(wù)狀態(tài)流轉(zhuǎn):
NEW -> COMPLETING -> NORMAL - 任務(wù)執(zhí)行異常時(shí),任務(wù)狀態(tài)流轉(zhuǎn):
NEW -> COMPLETING -> EXCEPTIONAL
所以,當(dāng)任務(wù)剛創(chuàng)建,或者是任務(wù)在執(zhí)行過(guò)程中,任務(wù)的狀態(tài)都是NEW
cancel源碼分析
此時(shí)再來(lái)分析cancel源碼
public boolean cancel(boolean mayInterruptIfRunning) {
// NEW為新建或者運(yùn)行態(tài)
// 1. 此時(shí)任務(wù)已經(jīng)不是NEW,說(shuō)明要么是完成要么是異常,取消不了,所以返回false
// 2. 此時(shí)任務(wù)還是NEW,如果我們傳入true,則CAS標(biāo)記任務(wù)為INTERRUPTING,否則是CANCELLED
// 防止并發(fā)取消任務(wù),CAS只會(huì)有一個(gè)線程成功,其余線程失敗
if (!(state == NEW && STATE.compareAndSet
(this, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try {
// 傳入true,則打斷該任務(wù)的執(zhí)行線程
if (mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally {
// 比較任務(wù)狀態(tài)為INTERRUPTED
STATE.setRelease(this, INTERRUPTED);
}
}
} finally {
finishCompletion();
}
return true;
}
通過(guò)對(duì)FutureTask任務(wù)狀態(tài)的認(rèn)知,再結(jié)合對(duì)cancel源碼的分析
我們可以總結(jié)出以下結(jié)論
當(dāng)任務(wù)已經(jīng)完成或者異常時(shí),無(wú)法取消任務(wù)
任務(wù)處于新建或者運(yùn)行狀態(tài)時(shí)
cancel方法入?yún)魅?code>true
將任務(wù)狀態(tài)NEW -> INTERRUPTING -> INTERRUPTED,并打斷執(zhí)行該任務(wù)的線程
cancel方法入?yún)魅?code>false
將任務(wù)狀態(tài)NEW -> CANCELLED
但有個(gè)問(wèn)題,傳入false只是將狀態(tài)從NEW變成CANCELLED嘛,這好像沒(méi)啥用?。?/p>
當(dāng)然不是,此時(shí)我們需要再回頭看看FutureTask的run方法
public void run() {
if (state != NEW ||
!RUNNER.compareAndSet(this, null, Thread.currentThread()))
return;
try {
Callable<V> c = callable;
if (c != null && state == NEW) {
V result;
boolean ran;
try {
result = c.call();
ran = true;
} catch (Throwable ex) {
result = null;
ran = false;
// 執(zhí)行異常
setException(ex);
}
if (ran)
// 正常執(zhí)行完畢
set(result);
}
} finally {
//... 省略
}
}
run方法開(kāi)頭我們可以看到,如果任務(wù)的狀態(tài)不是NEW,那么會(huì)直接return,不執(zhí)行任務(wù)
那此時(shí)再想想傳入false將任務(wù)狀態(tài)從NEW -> CANCELLED,是不是當(dāng)任務(wù)還沒(méi)有開(kāi)始執(zhí)行時(shí),我們cancel(false)就可以取消掉未執(zhí)行的任務(wù)了~
總結(jié)
通過(guò)上面的源碼解讀,我們大致能了解了cancel的機(jī)制,但是我們還是完善的總結(jié)一下
任務(wù)如果不是NEW狀態(tài)是不會(huì)執(zhí)行的
cancel取消任務(wù)會(huì)改變?nèi)蝿?wù)的狀態(tài)
- 如果傳入
true, 則將任務(wù)狀態(tài)NEW->INTERRUPTING->INTERRUPTED,并打斷執(zhí)行該任務(wù)的線程 - 如果傳入
false,將任務(wù)狀態(tài)NEW->CANCELLED
傳入false只能取消還未執(zhí)行的任務(wù)
傳入true,能取消未執(zhí)行的任務(wù),能打斷正在執(zhí)行的任務(wù)
擴(kuò)展知識(shí)點(diǎn)
在cancel源碼中,我們可以看到finally中會(huì)去調(diào)用finishCompletion
那么,finishCompletion是干啥的呢?
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
// 原子性將WAITERS設(shè)置為null
if (WAITERS.weakCompareAndSet(this, q, null)) {
// 遍歷WAITERS,將阻塞的線程都喚醒
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null;
q = next;
}
break;
}
}
?
// 擴(kuò)展方法,交給自己實(shí)現(xiàn)
done();
?
callable = null;
}
大家可以想想,當(dāng)我們submit一個(gè)任務(wù)時(shí),一般情況下都會(huì)需要去獲取他的返回值,會(huì)調(diào)用get方法進(jìn)行阻塞獲取
在FutureTask中,會(huì)維護(hù)一條鏈表,該鏈表記錄了等待獲取該任務(wù)返回值被阻塞的線程
在調(diào)用get方法時(shí),會(huì)將組裝waiters鏈表

所以,當(dāng)我們?nèi)∠粋€(gè)任務(wù)時(shí),是不是也應(yīng)該去將阻塞等待獲取該任務(wù)的所有線程進(jìn)行喚醒,而finishCompletion方法就是做這個(gè)事情的~
以上就是Future cancel迷惑性boolean入?yún)⒔馕龅脑敿?xì)內(nèi)容,更多關(guān)于Future cancel boolean入?yún)⒌馁Y料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能簡(jiǎn)單實(shí)例
這篇文章主要介紹了Java 實(shí)現(xiàn)隨機(jī)驗(yàn)證碼功能簡(jiǎn)單實(shí)例的相關(guān)資料,需要的朋友可以參考下2017-04-04
SpringBoot RestTemplate請(qǐng)求日志打印方式
這篇文章主要介紹了SpringBoot RestTemplate請(qǐng)求日志打印方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Java接口和抽象類(lèi)實(shí)現(xiàn)抽象和多態(tài)的方法示例
接口和抽象類(lèi)是 Java 中兩種實(shí)現(xiàn)抽象和多態(tài)的方法。它們之間有一些區(qū)別,但也有一些相似之處。這一節(jié)我們將通過(guò)詳細(xì)的例子來(lái)更深入地了解接口和抽象類(lèi)2023-05-05
詳解Java使用Pipeline對(duì)Redis批量讀寫(xiě)(hmset&hgetall)
本篇文章主要介紹了Java使用Pipeline對(duì)Redis批量讀寫(xiě)(hmset&hgetall),具有一定的參考價(jià)值,有興趣的可以了解一下。2016-12-12
Java 交換兩個(gè)變量的數(shù)值實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇Java 交換兩個(gè)變量的數(shù)值實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07
實(shí)例講解Java的設(shè)計(jì)模式編程中責(zé)任鏈模式的運(yùn)用
這篇文章主要介紹了Java的設(shè)計(jì)模式編程中責(zé)任鏈模式的運(yùn)用,講解了通過(guò)條件判斷結(jié)構(gòu)來(lái)分配不同對(duì)象的責(zé)任權(quán)限,需要的朋友可以參考下2016-02-02
JPA-JpaRepository方法命名語(yǔ)法說(shuō)明
這篇文章主要介紹了JPA-JpaRepository方法命名語(yǔ)法說(shuō)明,具有很好的參考價(jià)值。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-11-11
淺談Java中幾種常見(jiàn)的比較器的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇淺談Java中幾種常見(jiàn)的比較器的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10

