最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一起聊聊Java中13種鎖的實(shí)現(xiàn)方式

 更新時(shí)間:2022年08月05日 09:05:21   作者:Tom哥  
分布式系統(tǒng)時(shí)代,線程并發(fā),資源搶占,"鎖"?慢慢變得很重要。那么常見(jiàn)的鎖都有哪些?本文就來(lái)和大家聊聊Java中13種鎖的實(shí)現(xiàn)方式,感興趣的可以了解一下

最近有很多小伙伴給我留言,分布式系統(tǒng)時(shí)代,線程并發(fā),資源搶占,"鎖" 慢慢變得很重要。那么常見(jiàn)的鎖都有哪些?

今天Tom哥就和大家簡(jiǎn)單聊聊這個(gè)話題。

1、悲觀鎖

正如其名,它是指對(duì)數(shù)據(jù)修改時(shí)持保守態(tài)度,認(rèn)為其他人也會(huì)修改數(shù)據(jù)。因此在操作數(shù)據(jù)時(shí),會(huì)把數(shù)據(jù)鎖住,直到操作完成。悲觀鎖大多數(shù)情況下依靠數(shù)據(jù)庫(kù)的鎖機(jī)制實(shí)現(xiàn),以保證操作最大程度的獨(dú)占性。如果加鎖的時(shí)間過(guò)長(zhǎng),其他用戶長(zhǎng)時(shí)間無(wú)法訪問(wèn),影響程序的并發(fā)訪問(wèn)性,同時(shí)這樣對(duì)數(shù)據(jù)庫(kù)性能開(kāi)銷影響也很大,特別是長(zhǎng)事務(wù)而言,這樣的開(kāi)銷往往無(wú)法承受。

如果是單機(jī)系統(tǒng),我們可以采用 JAVA 自帶的 synchronized 關(guān)鍵字,通過(guò)添加到方法或同步塊上,鎖住資源 如果是分布式系統(tǒng),我們可以借助數(shù)據(jù)庫(kù)自身的鎖機(jī)制來(lái)實(shí)現(xiàn)。

select * from 表名 where id= #{id} for update

使用悲觀鎖的時(shí)候,我們要注意鎖的級(jí)別,MySQL innodb 在加鎖時(shí),只有明確的指定主鍵或(索引字段)才會(huì)使用 行鎖?;否則,會(huì)執(zhí)行 表鎖,將整個(gè)表鎖住,此時(shí)性能會(huì)很差。在使用悲觀鎖時(shí),我們必須關(guān)閉 MySQL 數(shù)據(jù)庫(kù)的自動(dòng)提交屬性,因?yàn)閙ysql默認(rèn)使用自動(dòng)提交模式。悲觀鎖適用于寫多的場(chǎng)景,而且并發(fā)性能要求不高。

2、樂(lè)觀鎖

樂(lè)觀鎖,從字面意思也能猜到個(gè)大概,在操作數(shù)據(jù)時(shí)非常樂(lè)觀,認(rèn)為別人不會(huì)同時(shí)修改數(shù)據(jù),因此樂(lè)觀鎖不會(huì)上鎖 只是在 提交更新? 時(shí),才會(huì)正式對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測(cè)。如果發(fā)現(xiàn)沖突了,則返回錯(cuò)誤信息,讓用戶決定如何去做,fail-fast 機(jī)制 。否則,執(zhí)行本次操作。

分為三個(gè)階段:數(shù)據(jù)讀取、寫入校驗(yàn)、數(shù)據(jù)寫入。

如果是單機(jī)系統(tǒng),我們可以基于JAVA 的 CAS來(lái)實(shí)現(xiàn),CAS 是一種原子操作,借助硬件的比較并交換來(lái)實(shí)現(xiàn)。

如果是分布式系統(tǒng),我們可以在數(shù)據(jù)庫(kù)表中增加一個(gè) 版本號(hào) 字段,如:version。

update 表 
set ... , version = version +1 
where id= #{id} and version = #{version}

操作前,先讀取記錄的版本號(hào),更新時(shí),通過(guò)SQL語(yǔ)句比較版本號(hào)是否一致。如果一致,則更新數(shù)據(jù)。否則會(huì)再次讀取版本,重試上面的操作。

3、分布式鎖

JAVA 中的 synchronized? 、ReentrantLock 等,都是解決單體應(yīng)用單機(jī)部署的資源互斥問(wèn)題。隨著業(yè)務(wù)快速發(fā)展,當(dāng)單體應(yīng)用演化為分布式集群后,多線程、多進(jìn)程分布在不同的機(jī)器上,原來(lái)的單機(jī)并發(fā)控制鎖策略失效

此時(shí)我們需要引入 分布式鎖,解決跨機(jī)器的互斥機(jī)制來(lái)控制共享資源的訪問(wèn)。

分布式鎖需要具備哪些條件:

  • 與單機(jī)系統(tǒng)一樣的資源互斥功能,這是鎖的基礎(chǔ)
  • 高性能獲取、釋放鎖
  • 高可用
  • 具備可重入性
  • 有鎖失效機(jī)制,防止死鎖
  • 非阻塞,不管是否獲得鎖,要能快速返回

實(shí)現(xiàn)方式多種多樣,基于 數(shù)據(jù)庫(kù)、Redis?、以及 Zookeeper等,這里講下主流的基于Redis的實(shí)現(xiàn)方式:

加鎖

SET key unique_value  [EX seconds] [PX milliseconds] [NX|XX]

通過(guò)原子命令,如果執(zhí)行成功返回 1,則表示加鎖成功。注意:unique_value 是客戶端生成的唯一標(biāo)識(shí),區(qū)分來(lái)自不同客戶端的鎖操作 解鎖要特別注意,先判斷 unique_value 是不是加鎖的客戶端,是的話才允許解鎖刪除。畢竟我們不能刪除其他客戶端加的鎖。

解鎖:解鎖有兩個(gè)命令操作,需要借助 Lua 腳本來(lái)保證原子性。

// 先比較 unique_value 是否相等,避免鎖的誤釋放
if redis.call("get",KEYS[1]) == ARGV[1] then
    return redis.call("del",KEYS[1])
else
    return 0
end

借助 Redis 的高性能,Redis 實(shí)現(xiàn)分布式鎖也是目前主流實(shí)現(xiàn)方式。但任何事情有利有弊,如果加鎖的服務(wù)器宕機(jī)了,當(dāng)slave 節(jié)點(diǎn)還沒(méi)來(lái)得及數(shù)據(jù)備份,那不是別的客戶端也可以獲得鎖。

為了解決這個(gè)問(wèn)題,Redis 官方設(shè)計(jì)了一個(gè)分布式鎖 Redlock。

基本思路:讓客戶端與多個(gè)獨(dú)立的 Redis 節(jié)點(diǎn)并行請(qǐng)求申請(qǐng)加鎖,如果能在半數(shù)以上的節(jié)點(diǎn)成功地完成加鎖操作,那么我們就認(rèn)為,客戶端成功地獲得分布式鎖,否則加鎖失敗。

4、可重入鎖

可重入鎖,也叫做遞歸鎖,是指在同一個(gè)線程在調(diào)外層方法獲取鎖的時(shí)候,再進(jìn)入內(nèi)層方法會(huì)自動(dòng)獲取鎖。

對(duì)象鎖或類鎖內(nèi)部有計(jì)數(shù)器,一個(gè)線程每獲得一次鎖,計(jì)數(shù)器 +1;解鎖時(shí),計(jì)數(shù)器 -1。

有多少次加鎖,就要對(duì)應(yīng)多少次解鎖,加鎖與解鎖成對(duì)出現(xiàn)。

Java 中的 ReentrantLock? 和 synchronized 都是 可重入鎖。可重入鎖的一個(gè)好處是可一定程度避免死鎖。

5、自旋鎖

自旋鎖是采用讓當(dāng)前線程不停地在循環(huán)體內(nèi)執(zhí)行,當(dāng)循環(huán)的條件被其他線程改變時(shí)才能進(jìn)入臨界區(qū)。自旋鎖只是將當(dāng)前線程不停地執(zhí)行循環(huán)體,不進(jìn)行線程狀態(tài)的改變,所以響應(yīng)速度更快。但當(dāng)線程數(shù)不斷增加時(shí),性能下降明顯,因?yàn)槊總€(gè)線程都需要執(zhí)行,會(huì)占用CPU時(shí)間片。如果線程競(jìng)爭(zhēng)不激烈,并且保持鎖的時(shí)間段。適合使用自旋鎖。

自旋鎖缺點(diǎn):

  • 可能引發(fā)死鎖。
  • 可能占用 CPU 的時(shí)間過(guò)長(zhǎng)。

我們可以設(shè)置一個(gè) 循環(huán)時(shí)間? 或 循環(huán)次數(shù)?,超出閾值時(shí),讓線程進(jìn)入阻塞狀態(tài),防止線程長(zhǎng)時(shí)間占用 CPU 資源。JUC 并發(fā)包中的 CAS 就是采用自旋鎖,compareAndSet 是CAS操作的核心,底層利用Unsafe對(duì)象實(shí)現(xiàn)的。

public final int getAndAddInt(Object var1, long var2, int var4) {
    int var5;
    do {
        var5 = this.getIntVolatile(var1, var2);
    } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
    return var5;
}

如果內(nèi)存中 var1 對(duì)象的var2字段值等于預(yù)期的 var5,則將該位置更新為新值(var5 + var4),否則不進(jìn)行任何操作,一直重試,直到操作成功為止。

CAS 包含了Compare和Swap 兩個(gè)操作,如何保證原子性呢?CAS 是由 CPU 支持的原子操作,其原子性是在硬件層面進(jìn)行控制。

特別注意,CAS 可能導(dǎo)致 ABA 問(wèn)題,我們可以引入遞增版本號(hào)來(lái)解決。

6、獨(dú)享鎖

獨(dú)享鎖,也有人叫它排他鎖。無(wú)論讀操作還是寫操作,只能有一個(gè)線程獲得鎖,其他線程處于阻塞狀態(tài)。

缺點(diǎn):讀操作并不會(huì)修改數(shù)據(jù),而且大部分的系統(tǒng)都是 讀多寫少?,如果讀讀之間互斥,大大降低系統(tǒng)的性能。下面的 共享鎖 會(huì)解決這個(gè)問(wèn)題。

像Java中的 ReentrantLock? 和 synchronized 都是獨(dú)享鎖。

7、共享鎖

共享鎖是指允許多個(gè)線程同時(shí)持有鎖,一般用在讀鎖上。讀鎖的共享鎖可保證并發(fā)讀是非常高效的。讀寫,寫讀 ,寫寫的則是互斥的。獨(dú)享鎖與共享鎖也是通過(guò)AQS來(lái)實(shí)現(xiàn)的,通過(guò)實(shí)現(xiàn)不同的方法,來(lái)實(shí)現(xiàn)獨(dú)享或者共享。

ReentrantReadWriteLock,其讀鎖是共享鎖,其寫鎖是獨(dú)享鎖。

8、讀鎖/寫鎖

如果對(duì)某個(gè)資源是讀操作,那多個(gè)線程之間并不會(huì)相互影響,可以通過(guò)添加讀鎖實(shí)現(xiàn)共享。如果有修改動(dòng)作,為了保證數(shù)據(jù)的并發(fā)安全,此時(shí)只能有一個(gè)線程獲得鎖,我們稱之為 寫鎖。讀讀是共享的;而 讀寫、寫讀 、寫寫 則是互斥的。

像 Java中的 ReentrantReadWriteLock 就是一種 讀寫鎖。

9、公平鎖/非公平鎖

公平鎖:多個(gè)線程按照申請(qǐng)鎖的順序去獲得鎖,所有線程都在隊(duì)列里排隊(duì),先來(lái)先獲取的公平性原則。

優(yōu)點(diǎn):所有的線程都能得到資源,不會(huì)餓死在隊(duì)列中。

缺點(diǎn):吞吐量會(huì)下降很多,隊(duì)列里面除了第一個(gè)線程,其他的線程都會(huì)阻塞,CPU 喚醒下一個(gè)阻塞線程有系統(tǒng)開(kāi)銷。

非公平鎖:多個(gè)線程不按照申請(qǐng)鎖的順序去獲得鎖,而是同時(shí)以插隊(duì)方式直接嘗試獲取鎖,獲取不到(插隊(duì)失敗),會(huì)進(jìn)入隊(duì)列等待(失敗則乖乖排隊(duì)),如果能獲取到(插隊(duì)成功),就直接獲取到鎖。

優(yōu)點(diǎn):可以減少 CPU 喚醒線程的開(kāi)銷,整體的吞吐效率會(huì)高點(diǎn)。

缺點(diǎn):可能導(dǎo)致隊(duì)列中排隊(duì)的線程一直獲取不到鎖或者長(zhǎng)時(shí)間獲取不到鎖,活活餓死。

Java 多線程并發(fā)操作,我們操作鎖大多時(shí)候都是基于 Sync? 本身去實(shí)現(xiàn)的,而 Sync 本身卻是 ReentrantLock? 的一個(gè)內(nèi)部類,Sync 繼承 AbstractQueuedSynchronizer。

像 ReentrantLock 默認(rèn)是非公平鎖,我們可以在構(gòu)造函數(shù)中傳入 true,來(lái)創(chuàng)建公平鎖。

public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

10、可中斷鎖/不可中斷鎖

可中斷鎖:指一個(gè)線程因?yàn)闆](méi)有獲得鎖在阻塞等待過(guò)程中,可以中斷自己阻塞的狀態(tài)。不可中斷鎖:恰恰相反,如果鎖被其他線程獲取后,當(dāng)前線程只能阻塞等待。如果持有鎖的線程一直不釋放鎖,那其他想獲取鎖的線程就會(huì)一直阻塞。

內(nèi)置鎖 synchronized 是不可中斷鎖,而 ReentrantLock 是可中斷鎖。

ReentrantLock獲取鎖定有三種方式:

  • lock(), 如果獲取了鎖立即返回,如果別的線程持有鎖,當(dāng)前線程則一直處于阻塞狀態(tài),直到該線程獲取鎖。
  • tryLock(), 如果獲取了鎖立即返回true,如果別的線程正持有鎖,立即返回false。
  • tryLock(long timeout,TimeUnit unit), 如果獲取了鎖定立即返回true,如果別的線程正持有鎖,會(huì)等待參數(shù)給定的時(shí)間,在等待的過(guò)程中,如果獲取了鎖定,就返回true,如果等待超時(shí),返回false。
  • lockInterruptibly(),如果獲取了鎖定立即返回;如果沒(méi)有獲取鎖,線程處于阻塞狀態(tài),直到獲取鎖或者線程被別的線程中斷。

更多:https://github.com/aalansehaiyang/p-java-proof/blob/master/resource/17.md。

11、分段鎖

分段鎖其實(shí)是一種鎖的設(shè)計(jì),目的是細(xì)化鎖的粒度,并不是具體的一種鎖,對(duì)于ConcurrentHashMap 而言,其并發(fā)的實(shí)現(xiàn)就是通過(guò)分段鎖的形式來(lái)實(shí)現(xiàn)高效的并發(fā)操作。

ConcurrentHashMap中的分段鎖稱為Segment,它即類似于HashMap(JDK7 中HashMap的實(shí)現(xiàn))的結(jié)構(gòu),即內(nèi)部擁有一個(gè)Entry數(shù)組,數(shù)組中的每個(gè)元素又是一個(gè)鏈表;同時(shí)又是一個(gè)ReentrantLock(Segment繼承了ReentrantLock)。

當(dāng)需要put元素的時(shí)候,并不是對(duì)整個(gè)HashMap加鎖,而是先通過(guò)hashcode知道要放在哪一個(gè)分段中,然后對(duì)這個(gè)分段加鎖,所以當(dāng)多線程put時(shí),只要不是放在同一個(gè)分段中,可支持并行插入。

12、鎖升級(jí)(無(wú)鎖|偏向鎖|輕量級(jí)鎖|重量級(jí)鎖)

JDK 1.6之前,synchronized 還是一個(gè)重量級(jí)鎖,效率比較低。但是在JDK 1.6后,JVM為了提高鎖的獲取與釋放效率對(duì) synchronized 進(jìn)行了優(yōu)化,引入了偏向鎖和輕量級(jí)鎖 ,從此以后鎖的狀態(tài)就有了四種:無(wú)鎖、偏向鎖、輕量級(jí)鎖、重量級(jí)鎖。這四種狀態(tài)會(huì)隨著競(jìng)爭(zhēng)的情況逐漸升級(jí),而且是不可降級(jí)。

無(wú)鎖

無(wú)鎖并不會(huì)對(duì)資源鎖定,所有的線程都可以訪問(wèn)并修改同一個(gè)資源,但同時(shí)只有一個(gè)線程能修改成功。也就是我們常說(shuō)的樂(lè)觀鎖。

偏向鎖

偏向于第一個(gè)訪問(wèn)鎖的線程,初次執(zhí)行synchronized代碼塊時(shí),通過(guò) CAS 修改對(duì)象頭里的鎖標(biāo)志位,鎖對(duì)象變成偏向鎖。

當(dāng)一個(gè)線程訪問(wèn)同步代碼塊并獲取鎖時(shí),會(huì)在 Mark Word? 里存儲(chǔ)鎖偏向的線程 ID。在線程進(jìn)入和退出同步塊時(shí)不再通過(guò) CAS 操作來(lái)加鎖和解鎖,而是檢測(cè) Mark Word 里是否存儲(chǔ)著指向當(dāng)前線程的偏向鎖。輕量級(jí)鎖的獲取及釋放依賴多次 CAS 原子指令,而偏向鎖只需要在置換 ThreadID 的時(shí)候依賴一次 CAS 原子指令即可。

執(zhí)行完同步代碼塊后,線程并不會(huì)主動(dòng)釋放偏向鎖。當(dāng)線程第二次再執(zhí)行同步代碼塊時(shí),線程會(huì)判斷此時(shí)持有鎖的線程是否就是自己(持有鎖的線程ID也在對(duì)象頭里),如果是則正常往下執(zhí)行。由于之前沒(méi)有釋放鎖,這里不需要重新加鎖,偏向鎖幾乎沒(méi)有額外開(kāi)銷,性能極高。

偏向鎖只有遇到其他線程嘗試競(jìng)爭(zhēng)偏向鎖時(shí),持有偏向鎖的線程才會(huì)釋放鎖,線程是不會(huì)主動(dòng)釋放偏向鎖的。關(guān)于偏向鎖的撤銷,需要等待全局安全點(diǎn),即在某個(gè)時(shí)間點(diǎn)上沒(méi)有字節(jié)碼正在執(zhí)行時(shí),它會(huì)先暫停擁有偏向鎖的線程,然后判斷鎖對(duì)象是否處于被鎖定狀態(tài)。如果線程不處于活動(dòng)狀態(tài),則將對(duì)象頭設(shè)置成無(wú)鎖狀態(tài),并撤銷偏向鎖,恢復(fù)到無(wú)鎖(標(biāo)志位為01)或輕量級(jí)鎖(標(biāo)志位為00)的狀態(tài)。

偏向鎖是指當(dāng)一段同步代碼一直被同一個(gè)線程所訪問(wèn)時(shí),即不存在多個(gè)線程的競(jìng)爭(zhēng)時(shí),那么該線程在后續(xù)訪問(wèn)時(shí)便會(huì)自動(dòng)獲得鎖,從而降低獲取鎖帶來(lái)的消耗。

輕量級(jí)鎖

當(dāng)前鎖是偏向鎖,此時(shí)有多個(gè)線程同時(shí)來(lái)競(jìng)爭(zhēng)鎖,偏向鎖就會(huì)升級(jí)為輕量級(jí)鎖。輕量級(jí)鎖認(rèn)為雖然競(jìng)爭(zhēng)是存在的,但是理想情況下競(jìng)爭(zhēng)的程度很低,通過(guò)自旋方式來(lái)獲取鎖。

輕量級(jí)鎖的獲取有兩種情況:

  • 當(dāng)關(guān)閉偏向鎖功能時(shí)。
  • 多個(gè)線程競(jìng)爭(zhēng)偏向鎖導(dǎo)致偏向鎖升級(jí)為輕量級(jí)鎖。一旦有第二個(gè)線程加入鎖競(jìng)爭(zhēng),偏向鎖就升級(jí)為輕量級(jí)鎖(自旋鎖)。

在輕量級(jí)鎖狀態(tài)下繼續(xù)鎖競(jìng)爭(zhēng),沒(méi)有搶到鎖的線程將自旋,不停地循環(huán)判斷鎖是否能夠被成功獲取。獲取鎖的操作,其實(shí)就是通過(guò)CAS修改對(duì)象頭里的鎖標(biāo)志位。先比較當(dāng)前鎖標(biāo)志位是否為“釋放”,如果是則將其設(shè)置為“鎖定”,此過(guò)程是原子性。如果搶到鎖,然后線程將當(dāng)前鎖的持有者信息修改為自己。

重量級(jí)鎖

如果線程的競(jìng)爭(zhēng)很激勵(lì),線程的自旋超過(guò)了一定次數(shù)(默認(rèn)循環(huán)10次,可以通過(guò)虛擬機(jī)參數(shù)更改),將輕量級(jí)鎖升級(jí)為重量級(jí)鎖(依然是 CAS  修改鎖標(biāo)志位,但不修改持有鎖的線程ID),當(dāng)后續(xù)線程嘗試獲取鎖時(shí),發(fā)現(xiàn)被占用的鎖是重量級(jí)鎖,則直接將自己掛起(而不是忙等),等待將來(lái)被喚醒。

重量級(jí)鎖是指當(dāng)有一個(gè)線程獲取鎖之后,其余所有等待獲取該鎖的線程都會(huì)處于阻塞狀態(tài)。簡(jiǎn)言之,就是所有的控制權(quán)都交給了操作系統(tǒng),由操作系統(tǒng)來(lái)負(fù)責(zé)線程間的調(diào)度和線程的狀態(tài)變更。而這樣會(huì)出現(xiàn)頻繁地對(duì)線程運(yùn)行狀態(tài)的切換,線程的掛起和喚醒,從而消耗大量的系統(tǒng)資。

13、鎖優(yōu)化技術(shù)(鎖粗化、鎖消除)

鎖粗化就是告訴我們?nèi)魏问虑槎加袀€(gè)度,有些情況下我們反而希望把很多次鎖的請(qǐng)求合并成一個(gè)請(qǐng)求,以降低短時(shí)間內(nèi)大量鎖請(qǐng)求、同步、釋放帶來(lái)的性能損耗。

舉個(gè)例子:有個(gè)循環(huán)體,內(nèi)部。

for(int i=0;i<size;i++){
    synchronized(lock){
        ...業(yè)務(wù)處理,省略
    }
}

經(jīng)過(guò)鎖粗化的代碼如下:

synchronized(lock){
    for(int i=0;i<size;i++){
        ...業(yè)務(wù)處理,省略
    }
}

鎖消除指的是在某些情況下,JVM 虛擬機(jī)如果檢測(cè)不到某段代碼被共享和競(jìng)爭(zhēng)的可能性,就會(huì)將這段代碼所屬的同步鎖消除掉,從而到底提高程序性能的目的。

鎖消除的依據(jù)是逃逸分析的數(shù)據(jù)支持,如 StringBuffer? 的 append()? 方法,或 Vector? 的 add() 方法,在很多情況下是可以進(jìn)行鎖消除的,比如以下這段代碼:

public String method() {
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < 10; i++) {
        sb.append("i:" + i);
    }
    return sb.toString();
}

以上代碼經(jīng)過(guò)編譯之后的字節(jié)碼如下:

從上述結(jié)果可以看出,之前我們寫的線程安全的加鎖的 StringBuffer? 對(duì)象,在生成字節(jié)碼之后就被替換成了不加鎖不安全的 StringBuilder? 對(duì)象了,原因是 StringBuffer 的變量屬于一個(gè)局部變量,并且不會(huì)從該方法中逃逸出去,所以我們可以使用鎖消除(不加鎖)來(lái)加速程序的運(yùn)行。

到此這篇關(guān)于一起聊聊Java中13種鎖的實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)Java鎖內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java泛型的簡(jiǎn)單實(shí)例

    Java泛型的簡(jiǎn)單實(shí)例

    這篇文章介紹了Java泛型的簡(jiǎn)單實(shí)例,有需要的朋友可以參考一下
    2013-10-10
  • MyBatis持久層框架的用法知識(shí)小結(jié)

    MyBatis持久層框架的用法知識(shí)小結(jié)

    MyBatis 本是apache的一個(gè)開(kāi)源項(xiàng)目iBatis,接下來(lái)通過(guò)本文給大家介紹MyBatis持久層框架的用法知識(shí)小結(jié),非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-07-07
  • IDEA連接達(dá)夢(mèng)數(shù)據(jù)庫(kù)的詳細(xì)配置指南

    IDEA連接達(dá)夢(mèng)數(shù)據(jù)庫(kù)的詳細(xì)配置指南

    達(dá)夢(mèng)數(shù)據(jù)庫(kù)(DM Database)作為國(guó)產(chǎn)關(guān)系型數(shù)據(jù)庫(kù)的代表,廣泛應(yīng)用于企業(yè)級(jí)系統(tǒng)開(kāi)發(fā),本文將詳細(xì)介紹如何在IntelliJ IDEA中配置并連接達(dá)夢(mèng)數(shù)據(jù)庫(kù),助力開(kāi)發(fā)者高效完成數(shù)據(jù)庫(kù)開(kāi)發(fā)工作,需要的朋友可以參考下
    2025-03-03
  • 定時(shí)任務(wù)@Scheduled用法及其參數(shù)使用

    定時(shí)任務(wù)@Scheduled用法及其參數(shù)使用

    這篇文章主要介紹了定時(shí)任務(wù)@Scheduled用法及其參數(shù)使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • java并發(fā)訪問(wèn)重復(fù)請(qǐng)求過(guò)濾問(wèn)題

    java并發(fā)訪問(wèn)重復(fù)請(qǐng)求過(guò)濾問(wèn)題

    本篇文章給大家分享了關(guān)于java并發(fā)訪問(wèn)重復(fù)請(qǐng)求過(guò)濾的相關(guān)問(wèn)題以及解決方法,對(duì)此有需要的朋友參考學(xué)習(xí)下。
    2018-05-05
  • java開(kāi)發(fā)命名規(guī)范總結(jié)

    java開(kāi)發(fā)命名規(guī)范總結(jié)

    包名的書(shū)寫規(guī)范 (Package)推薦使用公司或機(jī)構(gòu)的頂級(jí)域名為包名的前綴,目的是保證各公司/機(jī)構(gòu)內(nèi)所使用的包名的唯一性。包名全部為小寫字母,且具有實(shí)際的區(qū)分意義
    2013-10-10
  • Mybatis?XML配置文件實(shí)現(xiàn)增刪改查的示例代碼

    Mybatis?XML配置文件實(shí)現(xiàn)增刪改查的示例代碼

    本文主要介紹了Mybatis?XML配置文件實(shí)現(xiàn)增刪改查的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • Spring Cloud Gateway調(diào)用Feign異步問(wèn)題記錄

    Spring Cloud Gateway調(diào)用Feign異步問(wèn)題記錄

    這篇文章主要介紹了Spring Cloud Gateway調(diào)用Feign異步問(wèn)題記錄,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • IDEA標(biāo)簽tabs多行顯示的設(shè)置

    IDEA標(biāo)簽tabs多行顯示的設(shè)置

    這篇文章主要介紹了IDEA標(biāo)簽tabs多行顯示的設(shè)置方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2021-02-02
  • java整合微信支付功能詳細(xì)示例

    java整合微信支付功能詳細(xì)示例

    這篇文章主要給大家介紹了關(guān)于java整合微信支付功能的相關(guān)資料,支付是一個(gè)復(fù)雜且測(cè)試起來(lái)需要的配置特別復(fù)雜的模塊,文中給出了詳細(xì)的示例代碼,需要的朋友可以參考下
    2023-07-07

最新評(píng)論

吉水县| 彭山县| 克拉玛依市| 北京市| 大庆市| 密山市| 高要市| 阿拉善盟| 邻水| 循化| 理塘县| 响水县| 邛崃市| 印江| 新建县| 道孚县| 明星| 金坛市| 铅山县| 岳阳市| 河曲县| 天等县| 沛县| 新余市| 太仓市| 湾仔区| 桂东县| 蕉岭县| 乐安县| 连江县| 苏尼特左旗| 梁山县| 积石山| 明光市| 红安县| 昭通市| 内乡县| 重庆市| 天长市| 颍上县| 慈利县|