JUC容器介紹
JUC結(jié)構(gòu)

1. tools(工具類):又叫信號(hào)量三組工具類,包含有
1.CountDownLatch(倒計(jì)數(shù)) 是一個(gè)同步輔助類,在完成一組正在其他線程中執(zhí)行的操作之前,它允許一個(gè)或多個(gè)線程一直等待2.CyclicBarrier(循環(huán)柵欄) 之所以叫barrier,是因?yàn)槭且粋€(gè)同步輔助類,允許一組線程互相等待,直到到達(dá)某個(gè)公共屏障點(diǎn) ,并且在釋放等待線程后可以重用。3.Semaphore(信號(hào)量) 是一個(gè)計(jì)數(shù)信號(hào)量,它的本質(zhì)是一個(gè)“共享鎖“。信號(hào)量維護(hù)了一個(gè)信號(hào)量許可集。線程可以通過(guò)調(diào)用 acquire()來(lái)獲取信號(hào)量的許可;當(dāng)信號(hào)量中有可用的許可時(shí),線程能獲取該許可;否則線程必須等待,直到有可用的許可為止。線程可以通過(guò)release()來(lái)釋放它所持有的信號(hào)量許可。
2.executor(執(zhí)行者):是Java里面線程池的頂級(jí)接口,但它只是一個(gè)執(zhí)行線程的工具,真正的線程池接口是ExecutorService,里面包含的類有:
1.ScheduledExecutorService 解決那些需要任務(wù)重復(fù)執(zhí)行的問(wèn)題2.ScheduledThreadPoolExecutor 周期性任務(wù)調(diào)度的類實(shí)現(xiàn)
3.atomic(原子性包):是JDK提供的一組原子操作類,4.locks(鎖包):是JDK提供的鎖機(jī)制,相比synchronized關(guān)鍵字來(lái)進(jìn)行同步鎖,功能更加強(qiáng)大,它為鎖提供了一個(gè)框架,該框架允許更靈活地使用鎖包含的實(shí)現(xiàn)類有:
1.ReentrantLock 它是獨(dú)占鎖,是指只能被獨(dú)自占領(lǐng),即同一個(gè)時(shí)間點(diǎn)只能被一個(gè)線程鎖獲取到的鎖。2.ReentrantReadWriteLock 它包括子類ReadLock和WriteLock。ReadLock是共享鎖,而WriteLock是獨(dú)占鎖。3.LockSupport 它具備阻塞線程和解除阻塞線程的功能,并且不會(huì)引發(fā)死鎖[1]。
5.collections(集合類):主要是提供線程安全的集合, 比如:
1.ArrayList對(duì)應(yīng)的高并發(fā)類是CopyOnWriteArrayList,2.HashSet對(duì)應(yīng)的高并發(fā)類是 CopyOnWriteArraySet,3.HashMap對(duì)應(yīng)的高并發(fā)類是ConcurrentHashMap等等
1、tools(工具類)
JUC 中的同步器三個(gè)主要的成員:CountDownLatch、CyclicBarrier 和 Semaphore,通過(guò)它們可以方便地實(shí)現(xiàn)很多線程之間協(xié)作的功能。
CountDownLatch
叫倒計(jì)數(shù),允許一個(gè)或多個(gè)線程等待某些操作完成。
看幾個(gè)場(chǎng)景:1、跑步比賽,裁判需要等到所有的運(yùn)動(dòng)員(“其他線程”)都跑到終點(diǎn)(達(dá)到目標(biāo)),才能去算排名和頒獎(jiǎng)。
2、模擬并發(fā),我需要啟動(dòng) 100 個(gè)線程去同時(shí)訪問(wèn)某一個(gè)地址,我希望它們能同時(shí)并發(fā),而不是一個(gè)一個(gè)的去執(zhí)行。
用法:CountDownLatch 構(gòu)造方法指明計(jì)數(shù)數(shù)量,被等待線程調(diào)用 countDown 將計(jì)數(shù)器減 1,等待線程使用 await 進(jìn)行線程等待。
CyclicBarrier
叫循環(huán)柵欄,它實(shí)現(xiàn)讓一組線程等待至某個(gè)狀態(tài)之后再全部同時(shí)執(zhí)行,而且當(dāng)所有等待線程被釋放后,CyclicBarrier 可以被重復(fù)使用。CyclicBarrier 的典型應(yīng)用場(chǎng)景是用來(lái)等待并發(fā)線程結(jié)束。
CyclicBarrier 的主要方法是 await(),await() 每被調(diào)用一次,計(jì)數(shù)便會(huì)減少 1,并阻塞住當(dāng)前線程。當(dāng)計(jì)數(shù)減至 0 時(shí),阻塞解除,所有在此 CyclicBarrier 上面阻塞的線程開(kāi)始運(yùn)行。在這之后,如果再次調(diào)用 await(),計(jì)數(shù)就又會(huì)變成 N-1,新一輪重新開(kāi)始,這便是 Cyclic 的含義所在。CyclicBarrier.await() 帶有返回值,用來(lái)表示當(dāng)前線程是第幾個(gè)到達(dá)這個(gè) Barrier 的線程。
Semaphore
Java 版本的信號(hào)量實(shí)現(xiàn),用于控制同時(shí)訪問(wèn)的線程個(gè)數(shù),來(lái)達(dá)到限制通用資源訪問(wèn)的目的,其原理是通過(guò) acquire() 獲取一個(gè)許可,如果沒(méi)有就等待,而 release() 釋放一個(gè)許可。
如果 Semaphore 的數(shù)值被初始化為 1,那么一個(gè)線程就可以通過(guò) acquire 進(jìn)入互斥狀態(tài),本質(zhì)上和互斥鎖是非常相似的。
但是區(qū)別也非常明顯,比如互斥鎖是有持有者的,而對(duì)于 Semaphore 這種計(jì)數(shù)器結(jié)構(gòu),雖然有類似功能,但其實(shí)不存在真正意義的持有者,除非我們進(jìn)行擴(kuò)展包裝。
CyclicBarrier 和 CountDownLatch 區(qū)別
CountDownLatch 是不可以重置的,所以無(wú)法重用,CyclicBarrier 沒(méi)有這種限制,可以重用。
CountDownLatch 的基本操作組合是 countDown/await,調(diào)用 await 的線程阻塞等待 countDown 足夠的次數(shù),不管你是在一個(gè)線程還是多個(gè)線程里 countDown,只要次數(shù)足夠即可。CyclicBarrier 的基本操作組合就是 await,當(dāng)所有的伙伴都調(diào)用了 await,才會(huì)繼續(xù)進(jìn)行任務(wù),并自動(dòng)進(jìn)行重置。
CountDownLatch 目的是讓一個(gè)線程等待其他 N 個(gè)線程達(dá)到某個(gè)條件后,自己再去做某個(gè)事(通過(guò) CyclicBarrier 的第二個(gè)構(gòu)造方法 public CyclicBarrier(int parties, Runnable barrierAction),在新線程里做事可以達(dá)到同樣的效果)。
而 CyclicBarrier 的目的是讓 N 多線程互相等待直到所有的都達(dá)到某個(gè)狀態(tài),然后這 N 個(gè)線程再繼續(xù)執(zhí)行各自后續(xù)(通過(guò) CountDownLatch 在某些場(chǎng)合也能完成類似的效果)。
2、executor
關(guān)于線程池更多更詳細(xì)的請(qǐng)看之前的文章:
Java創(chuàng)建線程池的方式[2]
線程池的理解以及使用[3]
3、atomic
包含有AtomicBoolean、AtomicInteger、AtomicIntegerArray等原子變量類,他們的實(shí)現(xiàn)原理大多是持有它們各自的對(duì)應(yīng)的類型變量value,而且被volatile關(guān)鍵字修飾了。這樣來(lái)保證每次一個(gè)線程要使用它都會(huì)拿到最新的值。
4、Lock鎖(重點(diǎn))
什么是Synchronized?[4]
Synchronized和lock
1.Lock是一個(gè)接口,而synchronized是關(guān)鍵字。2.synchronized會(huì)自動(dòng)釋放鎖,而Lock必須手動(dòng)釋放鎖。3.Lock可以讓等待鎖的線程響應(yīng)中斷,而synchronized不會(huì),線程會(huì)一直等待下去。4.通過(guò)Lock可以知道線程有沒(méi)有拿到鎖,而synchronized不能。5.Lock能提高多個(gè)線程讀操作的效率。6.synchronized能鎖住類、方法和代碼塊,而Lock是塊范圍內(nèi)的
synchronized是Java的關(guān)鍵字,當(dāng)它用來(lái)修飾一個(gè)方法或者一個(gè)代碼塊的時(shí)候,能夠保證在同一時(shí)刻最多只有一個(gè)線程執(zhí)行該段代碼。JDK1.5以后引入了自旋鎖、鎖粗化、輕量級(jí)鎖,偏向鎖來(lái)有優(yōu)化關(guān)鍵字的性能。
Lock是一個(gè)接口,而synchronized是Java中的關(guān)鍵字,synchronized是內(nèi)置的語(yǔ)言實(shí)現(xiàn);synchronized在發(fā)生異常時(shí),會(huì)自動(dòng)釋放線程占有的鎖,因此不會(huì)導(dǎo)致死鎖現(xiàn)象發(fā)生;而Lock在發(fā)生異常時(shí),如果沒(méi)有主動(dòng)通過(guò)unLock()去釋放鎖,則很可能造成死鎖現(xiàn)象,因此使用Lock時(shí)需要在finally塊中釋放鎖;Lock可以讓等待鎖的線程響應(yīng)中斷,而synchronized卻不行,使用synchronized時(shí),等待的線程會(huì)一直等待下去,不能夠響應(yīng)中斷;通過(guò)Lock可以知道有沒(méi)有成功獲取鎖,而synchronized卻無(wú)法辦到。
更多鎖(ReentrantLock、ReadWriteLock讀寫鎖)的文章請(qǐng)關(guān)注更多文章
5、集合類不安全
ArrayList、HashSet、HashMap線程都不安全
在集合中 Vector 和 HashTable 是線程安全的。源碼中把各自核心方法添加上了synchronized 關(guān)鍵字。
Collections 工具類提供了相關(guān)的 API,可以讓上面那 3 個(gè)不安全的集合變?yōu)榘踩摹?/p>
1.Collections.synchronizedCollection(c)2.Collections.synchronizedList(list)3.Collections.synchronizedMap(m)4.Collections.synchronizedSet(s)
References
[2]?Java創(chuàng)建線程池的方式:?https://cuizb.top/myblog/article/1646793688[3]?線程池的理解以及使用:?https://cuizb.top/myblog/article/1638890023[4]?什么是Synchronized?:?https://cuizb.top/myblog/article/1639581387
