成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Java 多線程并發(fā)編程面試筆錄一覽

bitkylin / 1099人閱讀

摘要:創(chuàng)建線程的方式方式一將類聲明為的子類。將該線程標(biāo)記為守護(hù)線程或用戶線程。其中方法隱含的線程為父線程。恢復(fù)線程,已過時(shí)。等待該線程銷毀終止。更多的使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直等待,除非線

知識(shí)體系圖:

1、線程是什么?

線程是進(jìn)程中獨(dú)立運(yùn)行的子任務(wù)。

2、創(chuàng)建線程的方式

方式一:將類聲明為 Thread 的子類。該子類應(yīng)重寫 Thread 類的 run 方法

方式二:聲明實(shí)現(xiàn) Runnable 接口的類。該類然后實(shí)現(xiàn) run 方法

推薦方式二,因?yàn)榻涌诜绞奖壤^承方式更靈活,也減少程序間的耦合。

3、獲取當(dāng)前線程信息?

Thread.currentThread()

4、線程的分類

線程分為守護(hù)線程、用戶線程。線程初始化默認(rèn)為用戶線程。

setDaemon(true) 將該線程標(biāo)記為守護(hù)線程或用戶線程。

特性:設(shè)置守護(hù)線程,會(huì)作為進(jìn)程的守護(hù)者,如果進(jìn)程內(nèi)沒有其他非守護(hù)線程,那么守護(hù)線程也會(huì)被銷毀,即使可能線程內(nèi)沒有運(yùn)行結(jié)束。

5、線程間的關(guān)系?

某線程a 中啟動(dòng)另外一個(gè)線程 t,那么我們稱 線程 t是 線程a 的一個(gè)子線程,而 線程a 是 線程t 的 父線程。

最典型的就是我們?cè)趍ain方法中 啟動(dòng) 一個(gè) 線程去執(zhí)行。其中main方法隱含的main線程為父線程。

6、線程API一覽:如何啟動(dòng)、停止、暫停、恢復(fù)線程?

(1)start() 使線程處于就緒狀態(tài),Java虛擬機(jī)會(huì)調(diào)用該線程的run方法;

(2)stop() 停止線程,已過時(shí),存在不安全性:

一是可能請(qǐng)理性的工作得不得完成;

二是可能對(duì)鎖定的對(duì)象進(jìn)行“解鎖”,導(dǎo)致數(shù)據(jù)不同步不一致的情況。

推薦 使用 interrupt() +拋異常 中斷線程。

(3)suspend() 暫停線程,已過時(shí)。

resume() 恢復(fù)線程,已過時(shí)。

suspend 與resume 不建議使用,存在缺陷:

一是可能獨(dú)占同步對(duì)象;

二是導(dǎo)致數(shù)據(jù)不一致。

(4)yield() 放棄當(dāng)前線程的CPU資源。放棄時(shí)間不確認(rèn),也有可能剛剛放棄又獲得CPU資源。

(5)t.join() 等待該線程t 銷毀終止。

7、synchronized關(guān)鍵字用法

一 原子性(互斥性):實(shí)現(xiàn)多線程的同步機(jī)制,使得鎖內(nèi)代碼的運(yùn)行必需先獲得對(duì)應(yīng)的鎖,運(yùn)行完后自動(dòng)釋放對(duì)應(yīng)的鎖。

二 內(nèi)存可見性:在同一鎖情況下,synchronized鎖內(nèi)代碼保證變量的可見性。

三 可重入性:當(dāng)一個(gè)線程獲取一個(gè)對(duì)象的鎖,再次請(qǐng)求該對(duì)象的鎖時(shí)是可以再次獲取該對(duì)象的鎖的。

如果在synchronized鎖內(nèi)發(fā)生異常,鎖會(huì)被釋放。

總結(jié):

(1)synchronized方法 與 synchronized(this) 代碼塊 鎖定的都是當(dāng)前對(duì)象,不同的只是同步代碼的范圍

(2)synchronized (非this對(duì)象x) 將對(duì)象x本身作為“對(duì)象監(jiān)視器”:

a、多個(gè)線程同時(shí)執(zhí)行 synchronized(x) 代碼塊,呈現(xiàn)同步效果。

b、當(dāng)其他線程同時(shí)執(zhí)行對(duì)象x里面的 synchronized方法時(shí),呈現(xiàn)同步效果。

c、當(dāng)其他線程同時(shí)執(zhí)行對(duì)象x里面的 synchronized(this)方法時(shí),呈現(xiàn)同步效果。

(3)靜態(tài)synchronized方法 與 synchronized(calss)代碼塊 鎖定的都是Class鎖。Class 鎖與 對(duì)象鎖 不是同一個(gè)鎖,兩者同時(shí)使用情況可能呈異步效果。

(4)盡量不使用 synchronized(string),是因?yàn)閟tring的實(shí)際鎖為string的常量池對(duì)象,多個(gè)值相同的string對(duì)象可能持有同一個(gè)鎖。

8、volatile關(guān)鍵字用法

一 內(nèi)存可見性:保證變量的可見性,線程在每次使用變量的時(shí)候,都會(huì)讀取變量修改后的最的值。

二 不保證原子性。

9、線程間的通信方式

線程間通信的方式主要為共享內(nèi)存、線程同步。

線程同步除了synchronized互斥同步外,也可以使用wait/notify實(shí)現(xiàn)等待、通知的機(jī)制。

(1)wait/notify屬于Object類的方法,但wait和notify方法調(diào)用,必須獲取對(duì)象的對(duì)象級(jí)別鎖,即synchronized同步方法或同步塊中使用。

(2)wait()方法:在其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法前,或者其他某個(gè)線程中斷當(dāng)前線程,導(dǎo)致當(dāng)前線程一直阻塞等待。等同wait(0)方法。

wait(long timeout) 在其他線程調(diào)用此對(duì)象的 notify() 方法或 notifyAll() 方法,或者其他某個(gè)線程中斷當(dāng)前線程,或者已超過某個(gè)實(shí)際時(shí)間量前,導(dǎo)致當(dāng)前線程等待。 單位為毫秒。

void wait(long timeout, int nanos) 與 wait(long timeout) 不同的是增加了額外的納秒級(jí)別,更精細(xì)的等待時(shí)間控制。

(3)notfiy方法:?jiǎn)拘言诖藢?duì)象監(jiān)視器上等待的單個(gè)線程。選擇是任意性的,并在對(duì)實(shí)現(xiàn)做出決定時(shí)發(fā)生。線程通過調(diào)用其中一個(gè) wait 方法,在對(duì)象的監(jiān)視器上等待。

(4)notifyAll方法:?jiǎn)拘言诖藢?duì)象監(jiān)視器上等待的所有線程。

需要:wait被執(zhí)行后,會(huì)自動(dòng)釋放鎖,而notify被執(zhí)行后,鎖沒有立刻釋放,由synchronized同步塊結(jié)束時(shí)釋放。

應(yīng)用場(chǎng)景:簡(jiǎn)單的生產(chǎn)、消費(fèi)問題。

10、ThreadLocal與InheritableThreadLocal

讓每個(gè)線程都有自己獨(dú)立的共享變量,有兩種方式:

一 該實(shí)例變量封存在線程類內(nèi)部;如果該實(shí)例變量(非static)是引用類型,存在可能逸出的情況。

二 就是使用ThreadLocal在任意地方構(gòu)建變量,即使是靜態(tài)的(static)。具有很好的隔離性。

(1)重寫initialValue()方法: 初始化ThreadLocal變量,解決get()返回null問題(

(2)InheritableThreadLocal 子線程可以讀取父線程的值,但反之不行

11、ReentrantLock的使用

一個(gè)簡(jiǎn)單的示例:

ReentrantLock 比 synchronized 功能更強(qiáng)大,主要體現(xiàn):

(1)ReentrantLock 具有公平策略的選擇。

(2)ReentrantLock 可以在獲取鎖的時(shí)候,可有條件性地獲取,可以設(shè)置等待時(shí)間,很有效地避免死鎖。

如 tryLock() 和 tryLock(long timeout, TimeUnit unit)

(3)ReentrantLock 可以獲取鎖的各種信息,用于監(jiān)控鎖的各種狀態(tài)。

(4)ReentrantLock 可以靈活實(shí)現(xiàn)多路通知,即Condition的運(yùn)用。

————————————————————————————–

一、公平鎖與非公平鎖

ReentrantLock 默認(rèn)是非公平鎖,允許線程“搶占插隊(duì)”獲取鎖。公平鎖則是線程依照請(qǐng)求的順序獲取鎖,近似FIFO的策略方式。

二、鎖的使用:

(1)lock() 阻塞式地獲取鎖,只有在獲取到鎖后才處理interrupt信息

(2)lockInterruptibly() 阻塞式地獲取鎖,立即處理interrupt信息,并拋出異常

(3)tryLock() 嘗試獲取鎖,不管成功失敗,都立即返回true、false,注意的是即使已將此鎖設(shè)置為使用公平排序策略,tryLock()仍然可以打開公平性去插隊(duì)搶占。如果希望遵守此鎖的公平設(shè)置,則使用 tryLock(0, TimeUnit.SECONDS),它幾乎是等效的(也檢測(cè)中斷)。

(4)tryLock(long timeout, TimeUnit unit)在timeout時(shí)間內(nèi)阻塞式地獲取鎖,成功返回true,超時(shí)返回false,同時(shí)立即處理interrupt信息,并拋出異常。

如果想使用一個(gè)允許闖入公平鎖的定時(shí) tryLock,那么可以將定時(shí)形式和不定時(shí)形式組合在一起:

if (lock.tryLock() || lock.tryLock(timeout, unit) ) { … }

三、條件Condition的使用

條件Condition可以由鎖lock來創(chuàng)建,實(shí)現(xiàn)多路通知的機(jī)制。

具有await、signal、signalAll的方法,與wait/notify類似,需要在獲取鎖后方能調(diào)用。

12、ReentrantReadWriteLock的使用

ReentrantReadWriteLock是對(duì)ReentrantLock 更進(jìn)一步的擴(kuò)展,實(shí)現(xiàn)了讀鎖readLock()(共享鎖)和寫鎖writeLock()(獨(dú)占鎖),實(shí)現(xiàn)讀寫分離。讀和讀之間不會(huì)互斥,讀和寫、寫和讀、寫和寫之間才會(huì)互斥,提升了讀寫的性能。

讀鎖示例:

private final java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();
public void method() {
try {
lock.readLock().lock();
//獲取到讀鎖readLock,同步塊
} finally {
lock.readLock().unlock();//釋放讀鎖readLock
}
}
寫鎖示例:
private final java.util.concurrent.locks.ReadWriteLock lock = new ReentrantReadWriteLock();
public void method() {
try {
lock.writeLock().lock();
//獲取到寫鎖writeLock,同步塊
} finally {
lock.writeLock().unlock();//釋放寫鎖writeLock
}
}

13、同步容器與異步容器概覽

(1)同步容器

包括兩部分:

一個(gè)是早期JDK的Vector、Hashtable;

一個(gè)是它們的同系容器,JDK1.2加入的同步包裝類,使用Collections.synchronizedXxx工廠方法創(chuàng)建。

Map hashmapSync = Collections.synchronizedMap(new HashMap());
同步容器都是線程安全的,一次只有一個(gè)線程訪問容器的狀態(tài)。

但在某些場(chǎng)景下可能需要加鎖來保護(hù)復(fù)合操作。

復(fù)合類操作如:新增、刪除、迭代、跳轉(zhuǎn)以及條件運(yùn)算。

這些復(fù)合操作在多線程并發(fā)的修改容器時(shí),可能會(huì)表現(xiàn)出意外的行為,

最經(jīng)典的便是ConcurrentModificationException,

原因是當(dāng)容器迭代的過程中,被并發(fā)的修改了內(nèi)容,這是由于早期迭代器設(shè)計(jì)的時(shí)候并沒有考慮并發(fā)修改的問題。

其底層的機(jī)制無非就是用傳統(tǒng)的synchronized關(guān)鍵字對(duì)每個(gè)公用的方法都進(jìn)行同步,使得每次只能有一個(gè)線程訪問容器的狀態(tài)。這很明顯不滿足我們今天互聯(lián)網(wǎng)時(shí)代高并發(fā)的需求,在保證線程安全的同時(shí),也必須有足夠好的性能。

(2)并發(fā)容器

與Collections.synchronizedXxx()同步容器等相比,util.concurrent中引入的并發(fā)容器主要解決了兩個(gè)問題:

1)根據(jù)具體場(chǎng)景進(jìn)行設(shè)計(jì),盡量避免synchronized,提供并發(fā)性。

2)定義了一些并發(fā)安全的復(fù)合操作,并且保證并發(fā)環(huán)境下的迭代操作不會(huì)出錯(cuò)。

util.concurrent中容器在迭代時(shí),可以不封裝在synchronized中,可以保證不拋異常,但是未必每次看到的都是”最新的、當(dāng)前的”數(shù)據(jù)。

1
Map concurrentHashMap = new ConcurrentHashMap()
ConcurrentHashMap 替代同步的Map即(Collections.synchronized(new HashMap()))。眾所周知,HashMap是根據(jù)散列值分段存儲(chǔ)的,同步Map在同步的時(shí)候會(huì)鎖住整個(gè)Map,而ConcurrentHashMap在設(shè)計(jì)存儲(chǔ)的時(shí)候引入了段落Segment定義,同步的時(shí)候只需要鎖住根據(jù)散列值鎖住了散列值所在的段落即可,大幅度提升了性能。ConcurrentHashMap也增加了對(duì)常用復(fù)合操作的支持,比如”若沒有則添加”:putIfAbsent(),替換:replace()。這2個(gè)操作都是原子操作。注意的是ConcurrentHashMap 弱化了size()和isEmpty()方法,并發(fā)情況盡量少用,避免導(dǎo)致可能的加鎖(當(dāng)然也可能不加鎖獲得值,如果map數(shù)量沒有變化的話)。

CopyOnWriteArrayList和CopyOnWriteArraySet分別代替List和Set,主要是在遍歷操作為主的情況下來代替同步的List和同步的Set,這也就是上面所述的思路:迭代過程要保證不出錯(cuò),除了加鎖,另外一種方法就是”克隆”容器對(duì)象?!秉c(diǎn)也明顯,占有內(nèi)存,且數(shù)據(jù)最終一致,但數(shù)據(jù)實(shí)時(shí)不一定一致,一般用于讀多寫少的并發(fā)場(chǎng)景。

ConcurrentSkipListMap可以在高效并發(fā)中替代SoredMap(例如用Collections.synchronzedMap包裝的TreeMap)。

ConcurrentSkipListSet可以在高效并發(fā)中替代SoredSet(例如用Collections.synchronzedSet包裝的TreeMap)。

ConcurrentLinkedQuerue是一個(gè)先進(jìn)先出的隊(duì)列。它是非阻塞隊(duì)列。注意盡量用isEmpty,而不是size();

14、CountDownLatch閉鎖的使用

CountDownLatch是一個(gè)同步輔助類。

通常運(yùn)用場(chǎng)景:

(1)作為啟動(dòng)信號(hào):將計(jì)數(shù) 1 初始化的 CountDownLatch 用作一個(gè)簡(jiǎn)單的開/關(guān)鎖存器,或入口。

通俗描述:田徑賽跑運(yùn)動(dòng)員等待(每位運(yùn)動(dòng)員為一個(gè)線程,都在await())的”發(fā)令槍”,當(dāng)發(fā)令槍countDown(),喊0的時(shí)候,所有運(yùn)動(dòng)員跳過await()起跑線并發(fā)跑起來了。

(2)作為結(jié)束信號(hào):在通過調(diào)用 countDown() 的線程打開入口前,所有調(diào)用 await 的線程都一直在入口處等待。用 N 初始化的 CountDownLatch 可以使一個(gè)線程在 N 個(gè)線程完成某項(xiàng)操作之前一直等待,或者使其在某項(xiàng)操作完成 N 次之前一直等待。

通俗描述:某裁判,在終點(diǎn)等待所有運(yùn)動(dòng)員都跑完,每個(gè)運(yùn)動(dòng)員跑完就計(jì)數(shù)一次(countDown())當(dāng)為0時(shí),就可以往下繼續(xù)統(tǒng)計(jì)第一人到最后一個(gè)撞線的時(shí)間。

更多的api:

boolean await(long timeout, TimeUnit unit) 使當(dāng)前線程在鎖存器倒計(jì)數(shù)至零之前一直等待,除非線程被中斷或超出了指定的等待時(shí)間。

15、CyclicBarrier關(guān)卡的使用

CyclicBarrier是一個(gè)同步輔助類。

CyclicBarrier讓一個(gè)線程達(dá)到屏障時(shí)被阻塞,直到最后一個(gè)線程達(dá)到屏障時(shí),屏障才會(huì)開門,所有被屏障攔截的線程才會(huì)繼續(xù)執(zhí)行

CyclicBarrier(int parties, Runnable barrierAction)構(gòu)造函數(shù),用于在所有線程都到達(dá)屏障后優(yōu)先執(zhí)行barrierAction的run()方法

使用場(chǎng)景:

可以用于多線程計(jì)算以后,最后使用合并計(jì)算結(jié)果的場(chǎng)景;

通俗描述:某裁判,在終點(diǎn)(await()阻塞處)等待所有運(yùn)動(dòng)員都跑完,所有人都跑完就可以做吃炸雞啤酒(barrierAction),但是只要一個(gè)人沒跑完就都不能吃炸雞啤酒,當(dāng)然也沒規(guī)定他們同時(shí)跑(當(dāng)然也可以,一起使用CountDownLatch)。

————————————————————————————–

CyclicBarrier與CountDownLatch的區(qū)別:

CountDownLatch強(qiáng)調(diào)的是一個(gè)線程等待多個(gè)線程完成某件事,只能用一次,無法重置;

CyclicBarrier強(qiáng)調(diào)的是多個(gè)線程互相等待完成,才去做某個(gè)事情,可以重置。

更多api:

int await(long timeout, TimeUnit unit) 在所有參與者都已經(jīng)在此屏障上調(diào)用 await 方法之前將一直等待,或者超出了指定的等待時(shí)間。

16、Semaphore信號(hào)量的使用

Semaphore信號(hào)量是一個(gè)計(jì)數(shù)信號(hào)量。

可以認(rèn)為,Semaphore維護(hù)一個(gè)許可集。如有必要,在許可可用前會(huì)阻塞每一個(gè) acquire(),然后再獲取該許可。每個(gè) release() 添加一個(gè)許可,從而可能釋放一個(gè)正在阻塞的獲取者。

通俗描述:某個(gè)車庫(kù)只有N個(gè)車位,車主們要泊車,請(qǐng)向車庫(kù)保安處阻塞 acquire()等待獲取許可證,當(dāng)獲得許可證,車主們才可以去泊車。當(dāng)某個(gè)車主離開車位的時(shí)候,交還許可證release() ,從而其他阻塞等待的車主有機(jī)會(huì)獲得許可證。

另外:

Semaphore 默認(rèn)是非公平策略,允許線程“搶占插隊(duì)”獲取許可證。公平策略則是線程依照請(qǐng)求的順序獲取許可證,近似FIFO的策略方式。

17、Executors框架(線程池)的使用

(1)線程池是什么?

線程池是一種多線程的處理方式,利用已有線程對(duì)象繼續(xù)服務(wù)新的任務(wù)(按照一定的執(zhí)行策略),而不是頻繁地創(chuàng)建銷毀線程對(duì)象,由此提供服務(wù)的吞吐能力,減少CPU的閑置時(shí)間。具體組成部分包括:

a、線程池管理器(ThreadPool)用于創(chuàng)建和管理線程池,包括創(chuàng)建線程池、銷毀線程池,添加新任務(wù)。

b、工作線程(Worker)線程池中的線程,閑置的時(shí)候處于等待狀態(tài),可以循環(huán)回收利用。

c、任務(wù)接口(Task)每個(gè)任務(wù)必須實(shí)現(xiàn)的接口類,為工作線程提供調(diào)用,主要規(guī)定了任務(wù)的入口、任務(wù)完成的收尾工作、任務(wù)的狀態(tài)。

d、等待隊(duì)列(Queue)存放等待處理的任務(wù),提供緩沖機(jī)制。

(2)Executors框架常見的執(zhí)行策略

Executors框架提供了一些便利的執(zhí)行策略。

java.util.concurrent.ExecutorService service = java.util.concurrent.Executors.newFixedThreadPool(100);

newSingleThreadExecutor:創(chuàng)建一個(gè)單線程的線程池。

這個(gè)線程池只有一個(gè)線程在工作,也就是相當(dāng)于單線程串行執(zhí)行所有任務(wù)。如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束,那么會(huì)有一個(gè)新的線程來替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。

newFixedThreadPool:創(chuàng)建固定大小的線程池。

每次提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程,直到線程達(dá)到線程池的最大大小。線程池的大小一旦達(dá)到最大值就會(huì)保持不變,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束,那么線程池會(huì)補(bǔ)充一個(gè)新線程。

newCachedThreadPool:創(chuàng)建一個(gè)可緩存的線程池。

如果線程池的大小超過了處理任務(wù)所需要的線程,那么就會(huì)回收部分空閑(60秒不執(zhí)行任務(wù))的線程,當(dāng)任務(wù)數(shù)增加時(shí),此線程池又可以智能的添加新線程來處理任務(wù)。此線程池不會(huì)對(duì)線程池大小做限制,線程池大小完全依賴于操作系統(tǒng)(或者說JVM)能夠創(chuàng)建的最大線程大小。

newScheduledThreadPool:創(chuàng)建一個(gè)大小無限的線程池。

此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。

newSingleThreadScheduledExecutor:創(chuàng)建一個(gè)單線程的線程池。

此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求。

(3)ExecutorService線程池管理

ExecutorService的生命周期有3個(gè)狀態(tài):運(yùn)行、關(guān)閉(shutting down)、停止。

提交任務(wù)submit(xxx)擴(kuò)展了基本方法 Executor.execute(java.lang.Runnable)。

Future submit(Callable task) 提交一個(gè)返回值的任務(wù)用于執(zhí)行,返回一個(gè)表示任務(wù)的未決結(jié)果的 Future。

Future submit(Runnable task) 提交一個(gè) Runnable 任務(wù)用于執(zhí)行,并返回一個(gè)表示該任務(wù)的 Future。

Future submit(Runnable task, T result) 提交一個(gè) Runnable 任務(wù)用于執(zhí)行,并返回一個(gè)表示該任務(wù)的 Future。

shutdown() 啟動(dòng)一次順序關(guān)閉,執(zhí)行以前提交的任務(wù),但不接受新任務(wù)。

List shutdownNow() 試圖停止所有正在執(zhí)行的活動(dòng)任務(wù),暫停處理正在等待的任務(wù),并返回等待執(zhí)行的任務(wù)列表。

(3)ThreadPoolExecutor機(jī)制

ThreadPoolExecutor為Executors的線程池內(nèi)部實(shí)現(xiàn)類。

構(gòu)造函數(shù)詳解:

ThreadPoolExecutor線程池管理機(jī)制:

1.當(dāng)線程池小于corePoolSize時(shí),新提交任務(wù)將創(chuàng)建一個(gè)新線程執(zhí)行任務(wù),即使此時(shí)線程池中存在空閑線程。

2.當(dāng)線程池達(dá)到corePoolSize時(shí),新提交任務(wù)將被放入workQueue中,等待線程池中任務(wù)調(diào)度執(zhí)行

3.當(dāng)workQueue已滿,且maximumPoolSize>corePoolSize時(shí),新提交任務(wù)會(huì)創(chuàng)建新線程執(zhí)行任務(wù)

4.當(dāng)提交任務(wù)數(shù)超過maximumPoolSize時(shí),新提交任務(wù)由RejectedExecutionHandler處理

5.當(dāng)線程池中超過corePoolSize線程,空閑時(shí)間達(dá)到keepAliveTime時(shí),關(guān)閉空閑線程

6.當(dāng)設(shè)置allowCoreThreadTimeOut(true)時(shí),線程池中corePoolSize線程空閑時(shí)間達(dá)到keepAliveTime也將關(guān)閉

18、可攜帶結(jié)果的任務(wù)Callable 和 Future / FutureTask

(1)為解決Runnable接口不能返回一個(gè)值或受檢查的異常,可以采用Callable接口實(shí)現(xiàn)一個(gè)任務(wù)。

(2)Future表示異步計(jì)算的結(jié)果,可以對(duì)于具體的Runnable或者Callable任務(wù)進(jìn)行查詢是否完成,查詢是否取消,獲取執(zhí)行結(jié)果,取消任務(wù)等操作。

V get() throws InterruptedException, ExecutionException 如有必要,等待計(jì)算完成,然后獲取其結(jié)果。

V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException 如有必要,最多等待為使計(jì)算完成所給定的時(shí)間之后,獲取其結(jié)果(如果結(jié)果可用)。

(3)FutureTask

FutureTask則是一個(gè)RunnableFuture,而RunnableFuture實(shí)現(xiàn)了Runnbale又實(shí)現(xiàn)了Futrue這兩個(gè)接口。

注意的是提交到CompletionService中的Future是按照完成的順序排列的,而不是按照添加的順序排列的。

19、Atomic系列-原子變量類

其基本的特性就是在多線程環(huán)境下,當(dāng)有多個(gè)線程同時(shí)執(zhí)行這些類的實(shí)例包含的方法時(shí),具有排他性,即當(dāng)某個(gè)線程進(jìn)入方法,執(zhí)行其中的指令時(shí),不會(huì)被其他線程打斷,而別的線程就像自旋鎖一樣,一直等到該方法執(zhí)行完成,才由JVM從等待隊(duì)列中選擇一個(gè)另一個(gè)線程進(jìn)入,這只是一種邏輯上的理解。實(shí)際上是借助硬件的相關(guān)指令來實(shí)現(xiàn)的,不會(huì)阻塞線程(或者說只是在硬件級(jí)別上阻塞了)。其中的類可以分成4組

基本類:AtomicInteger、AtomicLong、AtomicBoolean;

引用類型:AtomicReference、AtomicStampedRerence、AtomicMarkableReference;–AtomicStampedReference 或者 AtomicMarkableReference 解決線程并發(fā)中,導(dǎo)致的ABA問題

數(shù)組類型:AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray —數(shù)組長(zhǎng)度固定不可變,但保證數(shù)組上每個(gè)元素的操作絕對(duì)安全的

屬性原子修改器(Updater):AtomicIntegerFieldUpdater、AtomicLongFieldUpdater、AtomicReferenceFieldUpdater

Updater使用限制:

限制1:操作的目標(biāo)不能是static類型,前面說到unsafe的已經(jīng)可以猜測(cè)到它提取的是非static類型的屬性偏移量,如果是static類型在獲取時(shí)如果沒有使用對(duì)應(yīng)的方法是會(huì)報(bào)錯(cuò)的,而這個(gè)Updater并沒有使用對(duì)應(yīng)的方法。

限制2:操作的目標(biāo)不能是final類型的,因?yàn)閒inal根本沒法修改。

限制3:必須是volatile類型的數(shù)據(jù),也就是數(shù)據(jù)本身是讀一致的。

限制4:屬性必須對(duì)當(dāng)前的Updater所在的區(qū)域是可見的,也就是private如果不是當(dāng)前類肯定是不可見的,protected如果不存在父子關(guān)系也是不可見的,default如果不是在同一個(gè)package下也是不可見的。

簡(jiǎn)單示例:
static class A {
volatile int intValue = 100;
}
private AtomicIntegerFieldUpdater atomicIntegerFieldUpdater
= AtomicIntegerFieldUpdater.newUpdater(A.class, "intValue");

20、總結(jié) 為什么要掌握線程開發(fā)技術(shù)?

多線程并發(fā)編程主要培養(yǎng)編程者深入了解最底層的運(yùn)作原理,加強(qiáng)編程者邏輯思維,這樣才能寫出高效、安全、可靠的多線程并發(fā)程序。

說到這里,順便給大家推薦一個(gè)架構(gòu)方面的交流學(xué)習(xí)群:650385180,里面會(huì)分享一些資深架構(gòu)師錄制的視頻錄像:有Spring,MyBatis,Netty源碼分析,高并發(fā)、高性能、分布式、微服務(wù)架構(gòu)的原理,JVM性能優(yōu)化這些成為架構(gòu)師必備的知識(shí)體系。還能領(lǐng)取免費(fèi)的學(xué)習(xí)資源,文章開頭的知識(shí)體系圖也是在群里面獲取的,相信對(duì)于已經(jīng)工作和遇到技術(shù)瓶頸的碼友,在這個(gè)群里會(huì)有你需要的內(nèi)容。

什么叫線程安全?

線程安全就是每次運(yùn)行結(jié)果和單線程運(yùn)行的結(jié)果是一樣的,而且其他的變量的值也和預(yù)期的是一樣的。

線程安全就是說多線程訪問同一代碼,不會(huì)產(chǎn)生不確定的結(jié)果。

線程安全問題多是由全局變量和靜態(tài)變量引起的,當(dāng)多個(gè)線程對(duì)共享數(shù)據(jù)只執(zhí)行讀操作,不執(zhí)行寫操作時(shí),一般是線程安全的;當(dāng)多個(gè)線程都執(zhí)行寫操作時(shí),需要考慮線程同步來解決線程安全問題。

什么叫線程同步?

多個(gè)線程操作一個(gè)資源的情況下,導(dǎo)致資源數(shù)據(jù)前后不一致。這樣就需要協(xié)調(diào)線程的調(diào)度,即線程同步。 解決多個(gè)線程使用共通資源的方法是:線程操作資源時(shí)獨(dú)占資源,其他線程不能訪問資源。使用鎖可以保證在某一代碼段上只有一條線程訪問共用資源。

有兩種方式實(shí)現(xiàn)線程同步:

1、synchronized

2、同步鎖(Lock)

什么叫線程通信?

有時(shí)候線程之間需要協(xié)作和通信。

有兩種方式實(shí)現(xiàn)線程通信:

1、synchronized 實(shí)現(xiàn)內(nèi)存可見性,滿足線程共享變量

2、wait/notifynotifyAll(synchronized同步方法或同步塊中使用) 實(shí)現(xiàn)內(nèi)存可見性,及生產(chǎn)消費(fèi)模式的相互喚醒機(jī)制

3、同步鎖(Lock)的Condition(awaitsignalsignalAll)

4、管道,實(shí)現(xiàn)數(shù)據(jù)的共享,滿足讀寫模式

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/76473.html

相關(guān)文章

  • jvm原理

    摘要:在之前,它是一個(gè)備受爭(zhēng)議的關(guān)鍵字,因?yàn)樵诔绦蛑惺褂盟占骼斫夂驮矸治龊?jiǎn)稱,是后提供的面向大內(nèi)存區(qū)數(shù)到數(shù)多核系統(tǒng)的收集器,能夠?qū)崿F(xiàn)軟停頓目標(biāo)收集并且具有高吞吐量具有更可預(yù)測(cè)的停頓時(shí)間。 35 個(gè) Java 代碼性能優(yōu)化總結(jié) 優(yōu)化代碼可以減小代碼的體積,提高代碼運(yùn)行的效率。 從 JVM 內(nèi)存模型談線程安全 小白哥帶你打通任督二脈 Java使用讀寫鎖替代同步鎖 應(yīng)用情景 前一陣有個(gè)做...

    lufficc 評(píng)論0 收藏0
  • Java線程學(xué)習(xí)(七)并發(fā)編程中一些問題

    摘要:相比與其他操作系統(tǒng)包括其他類系統(tǒng)有很多的優(yōu)點(diǎn),其中有一項(xiàng)就是,其上下文切換和模式切換的時(shí)間消耗非常少。因?yàn)槎嗑€程競(jìng)爭(zhēng)鎖時(shí)會(huì)引起上下文切換。減少線程的使用。很多編程語(yǔ)言中都有協(xié)程。所以如何避免死鎖的產(chǎn)生,在我們使用并發(fā)編程時(shí)至關(guān)重要。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)syn...

    dingding199389 評(píng)論0 收藏0
  • 這一次,讓我們完全掌握Java線程(2/10)

    摘要:多線程不僅是后端開發(fā)面試中非常熱門的一個(gè)問題,也是各種高級(jí)工具框架與分布式的核心基石。有興趣的讀者可以參考本系列的第一篇文章來了解一下并發(fā)相關(guān)的基本概念當(dāng)我們?cè)谡f并發(fā)多線程,說的是什么。 多線程不僅是Java后端開發(fā)面試中非常熱門的一個(gè)問題,也是各種高級(jí)工具、框架與分布式的核心基石。但是這個(gè)領(lǐng)域相關(guān)的知識(shí)點(diǎn)涉及到了線程調(diào)度、線程同步,甚至在一些關(guān)鍵點(diǎn)上還涉及到了硬件原語(yǔ)、操作系統(tǒng)等更底...

    zgbgx 評(píng)論0 收藏0
  • 想進(jìn)大廠?50個(gè)線程面試題,你會(huì)少?【后25題】(二)

    摘要:大多數(shù)待遇豐厚的開發(fā)職位都要求開發(fā)者精通多線程技術(shù)并且有豐富的程序開發(fā)調(diào)試優(yōu)化經(jīng)驗(yàn),所以線程相關(guān)的問題在面試中經(jīng)常會(huì)被提到。掌握了這些技巧,你就可以輕松應(yīng)對(duì)多線程和并發(fā)面試了。進(jìn)入等待通行準(zhǔn)許時(shí),所提供的對(duì)象。 最近看到網(wǎng)上流傳著,各種面試經(jīng)驗(yàn)及面試題,往往都是一大堆技術(shù)題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關(guān)線程的問題。Java語(yǔ)言一個(gè)重要的特點(diǎn)就...

    caozhijian 評(píng)論0 收藏0
  • Java線程學(xué)習(xí)(三)volatile關(guān)鍵字

    摘要:三關(guān)鍵字能保證原子性嗎并發(fā)編程藝術(shù)這本書上說保證但是在自增操作非原子操作上不保證,多線程編程核心藝術(shù)這本書說不保證。多線程訪問關(guān)鍵字不會(huì)發(fā)生阻塞,而關(guān)鍵字可能會(huì)發(fā)生阻塞關(guān)鍵字能保證數(shù)據(jù)的可見性,但不能保證數(shù)據(jù)的原子性。 系列文章傳送門: Java多線程學(xué)習(xí)(一)Java多線程入門 Java多線程學(xué)習(xí)(二)synchronized關(guān)鍵字(1) java多線程學(xué)習(xí)(二)synchroniz...

    tain335 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<