日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

高并发下Java多线程编程基础

發(fā)布時間:2024/8/23 java 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 高并发下Java多线程编程基础 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

摘要:?Java線程同步與異步 線程池 無鎖化的實(shí)現(xiàn)方案 分布鎖的實(shí)現(xiàn)方案 分享的目的: 進(jìn)一步掌握多線程編程和應(yīng)用的技巧,希望對大家在平時的開發(fā)中應(yīng)對高并發(fā)編程有所幫助 Java線程同步與異步 1. 同步相關(guān)的方法有 wait, notify, notifyAll 2.

Java線程同步與異步

線程池

無鎖化的實(shí)現(xiàn)方案

分布鎖的實(shí)現(xiàn)方案

分享的目的:

進(jìn)一步掌握多線程編程和應(yīng)用的技巧,希望對大家在平時的開發(fā)中應(yīng)對高并發(fā)編程有所幫助

Java線程同步與異步

1. 同步相關(guān)的方法有

wait, notify, notifyAll

2. 關(guān)鍵字

synchronized

3. JDK鎖的框架

AQS (AbstractQueuedSynchronizer)

4. AQS的實(shí)現(xiàn)類

java.util.concurrent.locks.ReentrantLock
java.util.concurrent.locks.ReentrantReadWriteLock
java.util.concurrent.CountDownLatch
java.util.concurrent.Semaphore

5. 例子——兩個線程交替打印出100以內(nèi)的奇數(shù)和偶數(shù)

主程序:


輸出結(jié)果示例:


...
...
...

思考:

讀者可以用兩種其它方法實(shí)現(xiàn),加深自己對Java線程同步和互斥的理解
用 ReentrantLock?
還是用wait和notify ?

線程池

作用:

控制線程并發(fā)數(shù)量,一般用在控制單機(jī)并發(fā)度上, 也是實(shí)現(xiàn)流控的一種方案;

實(shí)現(xiàn)原理:

1. 參數(shù)含義

corePoolSize: 核心線程的數(shù)量, 在CPU密集型和IO密集型的任務(wù)中,這個參數(shù)的設(shè)置不太一樣:

在CPU密集型的應(yīng)用中:

通常這個參數(shù)被設(shè)置為: 機(jī)器cpu核數(shù)-1, 例如機(jī)器有4個核,這個參數(shù)就被設(shè)置為3, 這樣做的即兼顧了最大的并發(fā)度,又兼顧了其它非重要的核心任務(wù)的執(zhí)行;

在IO密集的任務(wù)中:

通常這個參數(shù)被設(shè)置為機(jī)器cpu核數(shù)*(1.5 - 3),具體情況還需要根據(jù)實(shí)際業(yè)務(wù)情況進(jìn)行壓測比較,然后再給出最優(yōu)的值;
maximumPoolSize: 最大核心線程的數(shù)量
poolSize: 當(dāng)前線程的數(shù)量

當(dāng)用戶向線程池中新提交一個線程的時候,會有如下情況:

情況1.

如果當(dāng)前線程池中線程的數(shù)量小于corePoolSize, 就會創(chuàng)建一個新的線程, 并添加到線程池中;

情況2.

如果當(dāng)前線程池中線程的數(shù)量等于corePoolSize, 并且等待隊(duì)列中還沒有滿,則把當(dāng)前用戶添加的線程對象放在等待隊(duì)列中;

情況3.

如果當(dāng)前線程池中線程的數(shù)量大于等于corePoolSize并且小于maximunPoolSize,并且等待隊(duì)列已經(jīng)滿,則創(chuàng)建一個新的線程,并添加到線程池中;

情況4.

如果當(dāng)前線程池中線程的數(shù)量等于maximunPoolSize, 則會根據(jù)線程創(chuàng)建線程時候的拒絕策略,進(jìn)行相應(yīng)的處理;

2. java線程對象中run方法和start方法的區(qū)別:

2.1 線程對象直接調(diào)用run方法,JVM是不會有感知,是不會直接產(chǎn)生一個新的線程, 此時程序運(yùn)行的方式依然是串行的;
2.2 線程對象直接調(diào)用start方法,JVM才會有感知,會產(chǎn)生一個新的線程, 此時才會產(chǎn)生并發(fā)多線程;
線程池正是充分利用了run方法和start的區(qū)別來實(shí)現(xiàn)線程的復(fù)用;

3. 線程池的核心代碼

下面均是以jdk1.6的線程池的源碼,jdk1.7和jdk1.8線程池實(shí)現(xiàn)在上有些變化,但核心思想不變,有興趣可以自己去研究

提交線程的核心代碼:

執(zhí)行用戶任務(wù)的核心代碼:

無鎖化的實(shí)現(xiàn)方案

用線程池的方案

1. netty的reactor線程模型,參考netty官方或網(wǎng)上相關(guān)的資料

2. 異地機(jī)房數(shù)據(jù)庫之間的數(shù)據(jù)同步:

用表名+主鍵名做hash ,hash值相同的記錄被寫到同一個Kafka的Partition中去,假設(shè)一個Partition用一個線程進(jìn)行消費(fèi), 這樣不同線程之間寫入目標(biāo)數(shù)據(jù)庫的時候,就不會存在數(shù)據(jù)庫行鎖的競爭關(guān)系,間接實(shí)現(xiàn)了無鎖化的操作, 即線程之間并行,線程內(nèi)部串行, 如下圖所示;

用CAS的命令

1. JDK中各種類型值的原子操作

AtomicInteger
AtomicLong
AtomicBoolean

2. jdk中各種鎖的實(shí)現(xiàn), 本質(zhì)也是volitate變量+CAS

java.util.concurrent.locks.ReentrantLock
java.util.concurrent.Semaphore
java.util.concurrent.CountDownLatch

分布鎖的實(shí)現(xiàn)方案

1. tair

incr和decr操作,相當(dāng)于是樂觀鎖

2. Redis/memcache

setNx命令

3. Zookeeper

充分利用watcher機(jī)制,創(chuàng)建臨時結(jié)點(diǎn),誰創(chuàng)建成功,誰就獲得當(dāng)前的鎖

4. 數(shù)據(jù)庫:利用數(shù)據(jù)庫的行鎖

// 加鎖SQL
update trade_base set status = 1 where trade_no=“XXX” and status = 0;
// 解鎖SQL
update trade_base set status = 0 where trade_no=“XXX” and status = 1;
注意trade_base表上一要有trade_no的列的唯一索引

當(dāng)然具體用那種分布鎖,還需要結(jié)合業(yè)務(wù)自身的需要,一般來說,在并發(fā)量不是別大,數(shù)據(jù)庫完全可以扛得住的情況下,用數(shù)據(jù)庫實(shí)現(xiàn)分布鎖最快,最方便,而且性能的損失也非常地小;
當(dāng)然現(xiàn)在很多場景下,都是分庫分表,并且加鎖和解鎖分別都只影響一行,對數(shù)據(jù)庫來說,加鎖和解鎖的 sql也是非常輕量的sql操作,因此在性能損失上不用過多的擔(dān)心;

原文鏈接

本文為云棲社區(qū)原創(chuàng)內(nèi)容,未經(jīng)允許不得轉(zhuǎn)載。

總結(jié)

以上是生活随笔為你收集整理的高并发下Java多线程编程基础的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。