圖文詳解Java線程和線程池
一、什么是線程,線程和進(jìn)程的區(qū)別是什么
程序執(zhí)行流的最小執(zhí)行單位,是行程中的實(shí)際運(yùn)作單位,經(jīng)常容易和進(jìn)程這個(gè)概念混淆。那么,線程和進(jìn)程究竟有什么區(qū)別呢?首先,進(jìn)程是一個(gè)動(dòng)態(tài)的過(guò)程,是一個(gè)活動(dòng)的實(shí)體。簡(jiǎn)單來(lái)說(shuō),一個(gè)應(yīng)用程序的運(yùn)行就可以被看做是一個(gè)進(jìn)程,而線程,是運(yùn)行中的實(shí)際的任務(wù)執(zhí)行者??梢哉f(shuō),進(jìn)程中包含了多個(gè)可以同時(shí)運(yùn)行的線程。
二、線程中的基本概念,線程的生命周期
第一步,是用new Thread()的方法新建一個(gè)線程,在線程創(chuàng)建完成之后,線程就進(jìn)入了就緒(Runnable)狀態(tài),此時(shí)創(chuàng)建出來(lái)的線程進(jìn)入搶占CPU資源的狀態(tài),當(dāng)線程搶到了CPU的執(zhí)行權(quán)之后,線程就進(jìn)入了運(yùn)行狀態(tài)(Running),當(dāng)該線程的任務(wù)執(zhí)行完成之后或者是非常態(tài)的調(diào)用的stop()方法之后,線程就進(jìn)入了死亡狀態(tài)。而我們?cè)趫D解中可以看出,線程還具有一個(gè)則色的過(guò)程,這是怎么回事呢?當(dāng)面對(duì)以下幾種情況的時(shí)候,容易造成線程阻塞,第一種,當(dāng)線程主動(dòng)調(diào)用了sleep()方法時(shí),線程會(huì)進(jìn)入則阻塞狀態(tài),除此之外,當(dāng)線程中主動(dòng)調(diào)用了阻塞時(shí)的IO方法時(shí),這個(gè)方法有一個(gè)返回參數(shù),當(dāng)參數(shù)返回之前,線程也會(huì)進(jìn)入阻塞狀態(tài),還有一種情況,當(dāng)線程進(jìn)入正在等待某個(gè)通知時(shí),會(huì)進(jìn)入阻塞狀態(tài)。那么,為什么會(huì)有阻塞狀態(tài)出現(xiàn)呢?我們都知道,CPU的資源是十分寶貴的,所以,當(dāng)線程正在進(jìn)行某種不確定時(shí)長(zhǎng)的任務(wù)時(shí),Java就會(huì)收回CPU的執(zhí)行權(quán),從而合理應(yīng)用CPU的資源。我們根據(jù)圖可以看出,線程在阻塞過(guò)程結(jié)束之后,會(huì)重新進(jìn)入就緒狀態(tài),重新?lián)寠ZCPU資源。這時(shí)候,我們可能會(huì)產(chǎn)生一個(gè)疑問(wèn),如何跳出阻塞過(guò)程呢?又以上幾種可能造成線程阻塞的情況來(lái)看,都是存在一個(gè)時(shí)間限制的,當(dāng)sleep()方法的睡眠時(shí)長(zhǎng)過(guò)去后,線程就自動(dòng)跳出了阻塞狀態(tài),第二種則是在返回了一個(gè)參數(shù)之后,在獲取到了等待的通知時(shí),就自動(dòng)跳出了線程的阻塞過(guò)程
三、單線程和多線程
單線程,顧名思義即是只有一條線程在執(zhí)行任務(wù),這種情況在我們?nèi)粘5墓ぷ鲗W(xué)習(xí)中很少遇到,所以我們只是簡(jiǎn)單做一下了解
多線程,創(chuàng)建多條線程同時(shí)執(zhí)行任務(wù),這種方式在我們的日常生活中比較常見(jiàn)。但是,在多線程的使用過(guò)程中,還有許多需要我們了解的概念。比如,在理解上并行和并發(fā)的區(qū)別,以及在實(shí)際應(yīng)用的過(guò)程中多線程的安全問(wèn)題,對(duì)此,我們需要進(jìn)行詳細(xì)的了解。
并行和并發(fā):在我們看來(lái),都是可以同時(shí)執(zhí)行多種任務(wù),那么,到底他們二者有什么區(qū)別呢?
并發(fā),從宏觀方面來(lái)說(shuō),并發(fā)就是同時(shí)進(jìn)行多種時(shí)間,實(shí)際上,這幾種時(shí)間,并不是同時(shí)進(jìn)行的,而是交替進(jìn)行的,而由于CPU的運(yùn)算速度非常的快,會(huì)造成我們的一種錯(cuò)覺(jué),就是在同一時(shí)間內(nèi)進(jìn)行了多種事情
而并發(fā),則是真正意義上的同時(shí)進(jìn)行多種事情。這種只可以在多核CPU的基礎(chǔ)下完成。
還有就是多線程的安全問(wèn)題?為什么會(huì)造成多線程的安全問(wèn)題呢?我們可以想象一下,如果多個(gè)線程同時(shí)執(zhí)行一個(gè)任務(wù),name意味著他們共享同一種資源,由于線程CPU的資源不一定可以被誰(shuí)搶占到,這是,第一條線程先搶占到CPU資源,他剛剛進(jìn)行了第一次操作,而此時(shí)第二條線程搶占到了CPU的資源,name,共享資源還來(lái)不及發(fā)生變化,就同時(shí)有兩條數(shù)據(jù)使用了同一條資源,具體請(qǐng)參考多線程買(mǎi)票問(wèn)題。這個(gè)問(wèn)題我們應(yīng)該如何解決那?
有造成問(wèn)題的原因我們可以看出,這個(gè)問(wèn)題主要的矛盾在于,CPU的使用權(quán)搶占和資源的共享發(fā)生了沖突,解決時(shí),我們只需要讓一條線程戰(zhàn)歌了CPU的資源時(shí),阻止第二條線程同時(shí)搶占CPU的執(zhí)行權(quán),在代碼中,我們只需要在方法中使用同步代碼塊即可。在這里,同步代碼塊不多進(jìn)行贅述,可以自行了解。
四,線程池的原理解析
又以上介紹我們可以看出,在一個(gè)應(yīng)用程序中,我們需要多次使用線程,也就意味著,我們需要多次創(chuàng)建并銷(xiāo)毀線程。而創(chuàng)建并銷(xiāo)毀線程的過(guò)程勢(shì)必會(huì)消耗內(nèi)存。而在Java中,內(nèi)存資源是及其寶貴的,所以,我們就提出了線程池的概念。
線程池:Java中開(kāi)辟出了一種管理線程的概念,這個(gè)概念叫做線程池,從概念以及應(yīng)用場(chǎng)景中,我們可以看出,線程池的好處,就是可以方便的管理線程,也可以減少內(nèi)存的消耗。
那么,我們應(yīng)該如何創(chuàng)建一個(gè)線程池那?Java中已經(jīng)提供了創(chuàng)建線程池的一個(gè)類(lèi):Executor
而我們創(chuàng)建時(shí),一般使用它的子類(lèi):ThreadPoolExecutor.
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
這是其中最重要的一個(gè)構(gòu)造方法,這個(gè)方法決定了創(chuàng)建出來(lái)的線程池的各種屬性,下面依靠一張圖來(lái)更好的理解線程池和這幾個(gè)參數(shù):
又圖中,我們可以看出,線程池中的corePoolSize就是線程池中的核心線程數(shù)量,這幾個(gè)核心線程,只是在沒(méi)有用的時(shí)候,也不會(huì)被回收,maximumPoolSize就是線程池中可以容納的最大線程的數(shù)量,而keepAliveTime,就是線程池中除了核心線程之外的其他的最長(zhǎng)可以保留的時(shí)間,因?yàn)樵诰€程池中,除了核心線程即使在無(wú)任務(wù)的情況下也不能被清除,其余的都是有存活時(shí)間的,意思就是非核心線程可以保留的最長(zhǎng)的空閑時(shí)間,而util,就是計(jì)算這個(gè)時(shí)間的一個(gè)單位,workQueue,就是等待隊(duì)列,任務(wù)可以?xún)?chǔ)存在任務(wù)隊(duì)列中等待被執(zhí)行,執(zhí)行的是FIFIO原則(先進(jìn)先出)。threadFactory,就是創(chuàng)建線程的線程工廠,最后一個(gè)handler,是一種拒絕策略,我們可以在任務(wù)滿(mǎn)了知乎,拒絕執(zhí)行某些任務(wù)。
線程池的執(zhí)行流程又是怎樣的呢?
有圖我們可以看出,任務(wù)進(jìn)來(lái)時(shí),首先執(zhí)行判斷,判斷核心線程是否處于空閑狀態(tài),如果不是,核心線程就先就執(zhí)行任務(wù),如果核心線程已滿(mǎn),則判斷任務(wù)隊(duì)列是否有地方存放該任務(wù),若果有,就將任務(wù)保存在任務(wù)隊(duì)列中,等待執(zhí)行,如果滿(mǎn)了,在判斷最大可容納的線程數(shù),如果沒(méi)有超出這個(gè)數(shù)量,就開(kāi)創(chuàng)非核心線程執(zhí)行任務(wù),如果超出了,就調(diào)用handler實(shí)現(xiàn)拒絕策略。
handler的拒絕策略有四種:
AbortPolicy
:不執(zhí)行新任務(wù),直接拋出異常,提示線程池已滿(mǎn)DisCardPolicy
:不執(zhí)行新任務(wù),也不拋出異常
DisCardOldSetPolicy
:將消息隊(duì)列中的第一個(gè)任務(wù)替換為當(dāng)前新進(jìn)來(lái)的任務(wù)執(zhí)行
CallerRunsPolicy
:直接調(diào)用execute來(lái)執(zhí)行當(dāng)前任務(wù)
五,常見(jiàn)的幾種線程池的特點(diǎn)以及各自的應(yīng)用場(chǎng)景
CachedThreadPool
:可緩存的線程池,該線程池中沒(méi)有核心線程,非核心線程的數(shù)量為Integer.max_value,就是無(wú)限大,當(dāng)有需要時(shí)創(chuàng)建線程來(lái)執(zhí)行任務(wù),沒(méi)有需要時(shí)回收線程,適用于耗時(shí)少,任務(wù)量大的情況。
SecudleThreadPool
:周期性執(zhí)行任務(wù)的線程池,按照某種特定的計(jì)劃執(zhí)行線程中的任務(wù),有核心線程,但也有非核心線程,非核心線程的大小也為無(wú)限大。適用于執(zhí)行周期性的任務(wù)。
SingleThreadPool
:只有一條線程來(lái)執(zhí)行任務(wù),適用于有順序的任務(wù)的應(yīng)用場(chǎng)景。
FixedThreadPool
:定長(zhǎng)的線程池,有核心線程,核心線程的即為最大的線程數(shù)量,沒(méi)有非核心線程
總結(jié)
本篇文章就到這里了,希望能夠給你帶來(lái)幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
Java設(shè)計(jì)模式之橋接模式的實(shí)現(xiàn)
今天給大家?guī)?lái)的文章是Java設(shè)計(jì)模式的相關(guān)知識(shí)點(diǎn),文中對(duì)橋接模式作了非常詳細(xì)的介紹及代碼示例,對(duì)正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下2021-06-06mybatis plus CU自動(dòng)填充 和 軟刪除自動(dòng)填充的實(shí)現(xiàn)方法
這篇文章主要介紹了mybatis plus CU自動(dòng)填充 和 軟刪除自動(dòng)填充的實(shí)現(xiàn)方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07Java使用數(shù)組實(shí)現(xiàn)ArrayList的動(dòng)態(tài)擴(kuò)容的方法
這篇文章主要介紹了Java使用數(shù)組實(shí)現(xiàn)ArrayList的動(dòng)態(tài)擴(kuò)容的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06利用Java實(shí)現(xiàn)在PDF中添加工具提示
這篇文章主要介紹了如何通過(guò)Java在PDF中添加工具提示,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)或工作有一定的參考價(jià)值,感興趣的可以學(xué)習(xí)一下2022-01-01swing中Tree與滾動(dòng)條用法實(shí)例分析
這篇文章主要介紹了swing中Tree與滾動(dòng)條用法,以實(shí)例形式分析了java基于swing實(shí)現(xiàn)圖形界面的使用技巧,需要的朋友可以參考下2015-09-09Java swing實(shí)現(xiàn)支持錄音等功能的鋼琴程序
這篇文章主要為大家詳細(xì)介紹了Java swing實(shí)現(xiàn)鋼琴程序,支持錄音等功能的Java鋼琴源碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-06-06Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度條的文件下載
這篇文章主要為大家詳細(xì)介紹了Retrofit+RxJava實(shí)現(xiàn)帶進(jìn)度條的文件下載,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06