摘要:并發(fā)編程實(shí)戰(zhàn)水平很高,然而并不是本好書。一是多線程的控制,二是并發(fā)同步的管理。最后,使用和來(lái)關(guān)閉線程池,停止其中的線程。當(dāng)線程調(diào)用或等阻塞時(shí),對(duì)這個(gè)線程調(diào)用會(huì)使線程醒來(lái),并受到,且線程的中斷標(biāo)記被設(shè)置。
《Java并發(fā)編程實(shí)戰(zhàn)》水平很高,然而并不是本好書。組織混亂、長(zhǎng)篇大論、難以消化,中文翻譯也較死板。這里是一篇批評(píng)此書的帖子,很是貼切。俗話說(shuō):“看到有這么多人罵你,我就放心了”。
然而知識(shí)總是要學(xué)的。這里就總結(jié)一下書中及網(wǎng)絡(luò)上的內(nèi)容,作為Java并發(fā)編程之旅的結(jié)束,不再浪費(fèi)時(shí)間了。
兩個(gè)部分這本書實(shí)際上可以分為兩個(gè)部分。一是多線程的控制,二是并發(fā)同步的管理。把它們?nèi)嘣谝黄穑悸泛茈y清晰。本文就先介紹第一部分,多線程的控制。
Thread和Runnable在Java 5.0之前,多線程編程就是直接操作Thread。可以從Thread類派生一個(gè)類,或者實(shí)現(xiàn)Runnable接口的run()方法,然后調(diào)用Thread.start()啟動(dòng)線程。
線程的幾種狀態(tài):
Java 5.0增加了java.util.concurrent包,才有了線程池等強(qiáng)大的工具。
Java線程池參見(jiàn)Java線程池系列文章。本文略做總結(jié)。
阻塞隊(duì)列 BlockingQueue阻塞隊(duì)列,顧名思義,它在基本隊(duì)列的基礎(chǔ)上,還有阻塞的功能。即,如果隊(duì)列已滿,則入隊(duì)操作阻塞等待,直到有空位;如果隊(duì)列已空,則出隊(duì)操作阻塞等待,直到隊(duì)列有元素。相應(yīng)的方法分別為put()和take()。
阻塞隊(duì)列有幾種實(shí)現(xiàn):
ArrayBlockingQueue:基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列,按 FIFO(先進(jìn)先出)原則對(duì)元素進(jìn)行排序。
LinkedBlockingQueue:基于鏈表結(jié)構(gòu)的阻塞隊(duì)列,按FIFO排序元素,吞吐量通常要高于ArrayBlockingQueue。
SynchronousQueue:一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列。每個(gè)插入操作必須等到另一個(gè)線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài),吞吐量通常要高于LinkedBlockingQueue。
PriorityBlockingQueue:一個(gè)具有優(yōu)先級(jí)的無(wú)限阻塞隊(duì)列。
自己實(shí)現(xiàn)線程池就是一個(gè)簡(jiǎn)單的生產(chǎn)者、消費(fèi)者模型。線程池中的線程是消費(fèi)者,循環(huán)地從阻塞隊(duì)列中提取任務(wù),執(zhí)行任務(wù)。
Java線程池Java線程池的接口是ExecutorService,它有幾個(gè)實(shí)現(xiàn)。以ThreadPoolExecutor為例,它的使用方式是:
BlockingQueuequeue = new ArrayBlockingQueue (5); ExecutorService threadPoolExecutor = new ThreadPoolExecutor( corePoolSize, //初始線程數(shù) maxPoolSize, //最大線程數(shù) keepAliveTime, //空閑線程最大存活時(shí)間 TimeUnit.MILLISECONDS, //時(shí)間單位 queue // 任務(wù)的阻塞隊(duì)列 );
要使用這個(gè)線程池,可以使用它提供的如下方法:
execute(Runnable) 沒(méi)有返回值 。
submit(Runnable) 返回Future對(duì)象,代表未完成的結(jié)果(由于Runnable沒(méi)有返回值所以內(nèi)容為空)。
submit(Callable) 返回Future對(duì)象,代表未完成的結(jié)果。
invokeAny(Collection) 執(zhí)行所有任務(wù),返回第一個(gè)完成的結(jié)果。
invokeAll(Collection) 執(zhí)行所有任務(wù),返回Future對(duì)象列表。
最后,使用shutdown()和shutdownNow()來(lái)關(guān)閉線程池,停止其中的線程。前者采用后文講到的interrupt方式溫和關(guān)閉,后者則調(diào)用Thread.stop()強(qiáng)行關(guān)閉。
Executors類上面的線程池使用起來(lái)還是太具體了,還需要自己創(chuàng)建線程池,還要自己傳阻塞隊(duì)列進(jìn)去,不好用。于是Java提供了一個(gè)幫助類Executors,非常常用。
來(lái)看它的常用方法:
newFixedThreadPool(): 創(chuàng)建固定數(shù)量的線程池。
newCachedThreadPool(): 創(chuàng)建動(dòng)態(tài)維護(hù)線程數(shù)的線程池。
newSingleThreadExecutor(): 創(chuàng)建單線程的線程池。
Callable接口和Future接口Runnable接口的問(wèn)題在于沒(méi)有返回值,過(guò)于簡(jiǎn)單了。因此加入了Callable接口。相比于Runnable,一是有返回值,二是可以拋出異常。
Future就是異步編程中對(duì)一個(gè)還沒(méi)有完成的任務(wù)的抽象,相當(dāng)于C#中的Task。同樣有cancel()、isDone()等方法,調(diào)用get()則阻塞地獲取結(jié)果。
FutureTask是Future的一個(gè)具體實(shí)現(xiàn)類,并且不光實(shí)現(xiàn)了Future,還實(shí)現(xiàn)了Runnable接口,使其用舊方式也可調(diào)用。具體可見(jiàn) Runnable、Callable、Future、FutureTask的區(qū)別。
這是一個(gè)高級(jí)話題。Java建議不要用stop()粗暴地殺死線程,而是采用interrupt()這種溫和的方式。當(dāng)線程調(diào)用wait()或sleep()等阻塞時(shí),對(duì)這個(gè)線程調(diào)用interrupt()會(huì)使線程醒來(lái),并受到InterruptedException,且線程的中斷標(biāo)記被設(shè)置。如何處理這種情況取決于線程自己。具體參見(jiàn)這篇文章。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/68538.html
摘要:前言并發(fā)編程的目的是讓程序跑的更快,但并不是啟動(dòng)更多的線程,這個(gè)程序就跑的更快。盡可能降低上下文切換的次數(shù),有助于提高并發(fā)效率。死鎖并發(fā)編程中的另一挑戰(zhàn)是死鎖,會(huì)造成系統(tǒng)功能不可用。 前言 并發(fā)編程的目的是讓程序跑的更快,但并不是啟動(dòng)更多的線程,這個(gè)程序就跑的更快。有以下幾種挑戰(zhàn)。 挑戰(zhàn)及方案 上下文切換 單核CPU上執(zhí)行多線程任務(wù),通過(guò)給每個(gè)線程分配CPU時(shí)間片的方式來(lái)實(shí)現(xiàn)這個(gè)機(jī)制。...
摘要:本文探討并發(fā)中的其它問(wèn)題線程安全可見(jiàn)性活躍性等等。當(dāng)閉鎖到達(dá)結(jié)束狀態(tài)時(shí),門打開(kāi)并允許所有線程通過(guò)。在從返回時(shí)被叫醒時(shí),線程被放入鎖池,與其他線程競(jìng)爭(zhēng)重新獲得鎖。 本文探討Java并發(fā)中的其它問(wèn)題:線程安全、可見(jiàn)性、活躍性等等。 在行文之前,我想先推薦以下兩份資料,質(zhì)量很高:極客學(xué)院-Java并發(fā)編程讀書筆記-《Java并發(fā)編程實(shí)戰(zhàn)》 線程安全 《Java并發(fā)編程實(shí)戰(zhàn)》中提到了太多的術(shù)語(yǔ)...
摘要:目前看的部分主要是這個(gè)關(guān)鍵字。語(yǔ)言提供了,保證了所有線程能看到共享變量最新的值。前綴的指令在多核處理器下會(huì)做兩件事情將當(dāng)前處理器緩存行的數(shù)據(jù)寫回到系統(tǒng)內(nèi)存。 這一章節(jié)的話,主要是講一下在并發(fā)操作中常見(jiàn)的volatile、synchronized以及原子操作的相關(guān)知識(shí)。 目前看的部分主要是volatile這個(gè)關(guān)鍵字。 volatile 根據(jù)Java語(yǔ)言規(guī)范第3版中對(duì)volatile的定義...
摘要:純分享直接上干貨操作系統(tǒng)并發(fā)支持進(jìn)程管理內(nèi)存管理文件系統(tǒng)系統(tǒng)進(jìn)程間通信網(wǎng)絡(luò)通信阻塞隊(duì)列數(shù)組有界隊(duì)列鏈表無(wú)界隊(duì)列優(yōu)先級(jí)有限無(wú)界隊(duì)列延時(shí)無(wú)界隊(duì)列同步隊(duì)列隊(duì)列內(nèi)存模型線程通信機(jī)制內(nèi)存共享消息傳遞內(nèi)存模型順序一致性指令重排序原則內(nèi)存語(yǔ)義線程 純分享 , 直接上干貨! 操作系統(tǒng)并發(fā)支持 進(jìn)程管理內(nèi)存管...
摘要:前言今天的筆記來(lái)了解一下原子操作以及中如何實(shí)現(xiàn)原子操作。概念原子本意是不能被進(jìn)一步分割的最小粒子,而原子操作意為不可被中斷的一個(gè)或一系列操作。處理器實(shí)現(xiàn)原子操作處理器會(huì)保證基本內(nèi)存操作的原子性。 showImg(https://segmentfault.com/img/bVVIRA?w=1242&h=536); 前言 今天的筆記來(lái)了解一下原子操作以及Java中如何實(shí)現(xiàn)原子操作。 概念 ...
閱讀 837·2021-11-18 10:07
閱讀 2355·2021-10-14 09:42
閱讀 5315·2021-09-22 15:45
閱讀 585·2021-09-03 10:29
閱讀 3462·2021-08-31 14:28
閱讀 1873·2019-08-30 15:56
閱讀 3038·2019-08-30 15:54
閱讀 994·2019-08-29 11:32