Java是一種可以撰寫跨平臺(tái)應(yīng)用軟件的面向?qū)ο蟮某绦蛟O(shè)計(jì)語(yǔ)言追迟。Java 技術(shù)具有卓越的通用性、高效性骚腥、平臺(tái)移植性和安全性敦间,廣泛應(yīng)用于PC、數(shù)據(jù)中心、游戲控制臺(tái)廓块、科學(xué)超級(jí)計(jì)算機(jī)金闽、移動(dòng)電話和互聯(lián)網(wǎng),同時(shí)擁有全球最大的開發(fā)者專業(yè)社群剿骨。
給你學(xué)習(xí)路線:html-css-js-jq-javase-數(shù)據(jù)庫(kù)-jsp-servlet-Struts2-hibernate-mybatis-spring4-springmvc-ssh-ssm
先看幾個(gè)概念:
線程:進(jìn)程中負(fù)責(zé)程序執(zhí)行的執(zhí)行單元代芜。一個(gè)進(jìn)程中至少有一個(gè)線程。
多線程:解決多任務(wù)同時(shí)執(zhí)行的需求浓利,合理使用CPU資源挤庇。多線程的運(yùn)行是根據(jù)CPU切換完成,如何切換由CPU決定贷掖,因此多線程運(yùn)行具有不確定性嫡秕。
線程池:基本思想還是一種對(duì)象池的思想,開辟一塊內(nèi)存空間苹威,里面存放了眾多(未死亡)的線程昆咽,池中線程執(zhí)行調(diào)度由池管理器來處理。當(dāng)有線程任務(wù)時(shí)牙甫,從池中取一個(gè)掷酗,執(zhí)行完成后線程對(duì)象歸池,這樣可以避免反復(fù)創(chuàng)建線程對(duì)象所帶來的性能開銷窟哺,節(jié)省了系統(tǒng)的資源泻轰。
● 線程
創(chuàng)建線程的兩種方式:
一、繼承Thread類且轨,擴(kuò)展線程浮声。
小編推薦一個(gè)學(xué)Java的學(xué)習(xí)裙【 六五零,五五四旋奢,六零七 】泳挥,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)至朗!裙內(nèi)有開發(fā)工具屉符,很多干貨和技術(shù)資料分享!
繼承Thread類爽丹,覆蓋run()方法筑煮。
創(chuàng)建線程對(duì)象并用start()方法啟動(dòng)線程。
面試題
1)線程和進(jìn)程有什么區(qū)別粤蝎?
一個(gè)進(jìn)程是一個(gè)獨(dú)立(self contained)的運(yùn)行環(huán)境真仲,它可以被看作一個(gè)程序或者一個(gè)應(yīng)用。而線程是在進(jìn)程中執(zhí)行的一個(gè)任務(wù)初澎。線程是進(jìn)程的子集秸应,一個(gè)進(jìn)程可以有很多線程虑凛,每條線程并行執(zhí)行不同的任務(wù)。不同的進(jìn)程使用不同的內(nèi)存空間软啼,而所有的線程共享一片相同的內(nèi)存空間桑谍。別把它和棧內(nèi)存搞混,每個(gè)線程都擁有單獨(dú)的棧內(nèi)存用來存儲(chǔ)本地?cái)?shù)據(jù)祸挪。
2)如何在Java中實(shí)現(xiàn)線程锣披?
創(chuàng)建線程有兩種方式:
1. 繼承 Thread 類,擴(kuò)展線程贿条。
2. 實(shí)現(xiàn) Runnable 接口雹仿。
3)Thread 類中的 start() 和 run() 方法有什么區(qū)別?
調(diào)用 start() 方法才會(huì)啟動(dòng)新線程整以;如果直接調(diào)用 Thread 的 run() 方法胧辽,它的行為就會(huì)和普通的方法一樣;為了在新的線程中執(zhí)行我們的代碼公黑,必須使用 Thread.start() 方法邑商。
二、實(shí)現(xiàn)Runnable接口凡蚜。
面試題
1)用 Runnable 還是 Thread 人断?
我們都知道可以通過繼承 Thread 類或者調(diào)用 Runnable 接口來實(shí)現(xiàn)線程,問題是番刊,創(chuàng)建線程哪種方式更好呢含鳞?什么情況下使用它?這個(gè)問題很容易回答芹务,如果你知道Java不支持類的多重繼承,但允許你調(diào)用多個(gè)接口鸭廷。所以如果你要繼承其他類枣抱,當(dāng)然是調(diào)用Runnable接口更好了。
2)Runnable 和 Callable 有什么不同辆床?
Runnable 和 Callable 都代表那些要在不同的線程中執(zhí)行的任務(wù)佳晶。Runnable 從 JDK1.0 開始就有了,Callable 是在 JDK1.5 增加的讼载。它們的主要區(qū)別是 Callable 的 call() 方法可以返回值和拋出異常轿秧,而 Runnable 的 run() 方法沒有這些功能。Callable 可以返回裝載有計(jì)算結(jié)果的 Future 對(duì)象咨堤。
擴(kuò)展
先看一下 Runnable 和 Callable 的源碼
可以得出:
1)Callable 接口下的方法是 call()菇篡,Runnable 接口的方法是 run()。
2)Callable 的任務(wù)執(zhí)行后可返回值一喘,而 Runnable 的任務(wù)是不能返回值的驱还。
3)call() 方法可以拋出異常,run()方法不可以的。
4)運(yùn)行 Callable 任務(wù)可以拿到一個(gè) Future 對(duì)象议蟆,表示異步計(jì)算的結(jié)果闷沥。它提供了檢查計(jì)算是否完成的方法,以等待計(jì)算的完成咐容,并檢索計(jì)算的結(jié)果舆逃。通過 Future 對(duì)象可以了解任務(wù)執(zhí)行情況,可取消任務(wù)的執(zhí)行戳粒,還可獲取執(zhí)行結(jié)果颖侄。
但是,但是享郊,凡事都有但是嘛...
單獨(dú)使用 Callable览祖,無法在新線程中(new Thread(Runnable r))使用,Thread 類只支持 Runnable炊琉。不過 Callable 可以使用 ExecutorService (又拋出一個(gè)概念展蒂,這個(gè)概念將在下面的線程池中說明)。
上面又提到了 Future苔咪,看一下 Future 接口:
Future 定義了5個(gè)方法:
1)boolean cancel(boolean mayInterruptIfRunning):試圖取消對(duì)此任務(wù)的執(zhí)行锰悼。如果任務(wù)已完成、或已取消团赏,或者由于某些其他原因而無法取消箕般,則此嘗試將失敗。當(dāng)調(diào)用 cancel() 時(shí)舔清,如果調(diào)用成功丝里,而此任務(wù)尚未啟動(dòng),則此任務(wù)將永不運(yùn)行体谒。如果任務(wù)已經(jīng)啟動(dòng)杯聚,則 mayInterruptIfRunning 參數(shù)確定是否應(yīng)該以試圖停止任務(wù)的方式來中斷執(zhí)行此任務(wù)的線程。此方法返回后抒痒,對(duì) isDone() 的后續(xù)調(diào)用將始終返回 true幌绍。如果此方法返回 true,則對(duì) isCancelled() 的后續(xù)調(diào)用將始終返回 true故响。
2)boolean isCancelled():如果在任務(wù)正常完成前將其取消傀广,則返回 true。
3)boolean isDone():如果任務(wù)已完成彩届,則返回 true伪冰。 可能由于正常終止、異巢依拢或取消而完成糜值,在所有這些情況中丰捷,此方法都將返回 true。
4)V get()throws InterruptedException,ExecutionException:如有必要寂汇,等待計(jì)算完成病往,然后獲取其結(jié)果。
5)V get(long timeout,TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException: 如有必要骄瓣,最多等待為使計(jì)算完成所給定的時(shí)間之后停巷,獲取其結(jié)果(如果結(jié)果可用)。
看來 Future 接口也不能用在線程中榕栏,那怎么用畔勤,誰(shuí)實(shí)現(xiàn)了 Future 接口呢?答:FutureTask扒磁。
FutureTask 實(shí)現(xiàn)了 Runnable 和 Future庆揪,所以兼顧兩者優(yōu)點(diǎn),既可以在 Thread 中使用妨托,又可以在 ExecutorService 中使用缸榛。
看完上面啰哩啰嗦的介紹后,下面我們具體看一下具體使用的示例:
小編推薦一個(gè)學(xué)Java的學(xué)習(xí)裙【 六五零兰伤,五五四内颗,六零七 】,無論你是大牛還是小白敦腔,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)均澳!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享符衔!
使用 FutureTask 的好處是 FutureTask 是為了彌補(bǔ) Thread 的不足而設(shè)計(jì)的找前,它可以讓程序員準(zhǔn)確地知道線程什么時(shí)候執(zhí)行完成并獲得到線程執(zhí)行完成后返回的結(jié)果。FutureTask 是一種可以取消的異步的計(jì)算任務(wù)柏腻,它的計(jì)算是通過 Callable 實(shí)現(xiàn)的纸厉,它等價(jià)于可以攜帶結(jié)果的 Runnable,并且有三個(gè)狀態(tài):等待五嫂、運(yùn)行和完成。完成包括所有計(jì)算以任意的方式結(jié)束肯尺,包括正常結(jié)束沃缘、取消和異常。
● 多線程
多線程的概念很好理解就是多條線程同時(shí)存在则吟,但要用好多線程確不容易槐臀,涉及到多線程間通信,多線程共用一個(gè)資源等諸多問題氓仲。
使用多線程的優(yōu)缺點(diǎn):
優(yōu)點(diǎn):
1)適當(dāng)?shù)奶岣叱绦虻膱?zhí)行效率(多個(gè)線程同時(shí)執(zhí)行)水慨。
2)適當(dāng)?shù)奶岣吡速Y源利用率(CPU得糜、內(nèi)存等)。
缺點(diǎn):
1)占用一定的內(nèi)存空間晰洒。
2)線程越多CPU的調(diào)度開銷越大朝抖。
3)程序的復(fù)雜度會(huì)上升。
對(duì)于多線程的示例代碼感興趣的可以自己寫Demo啦谍珊,去運(yùn)行體會(huì)治宣,下面我主要列出一些多線程的技術(shù)點(diǎn)。
synchronized
同步塊大家都比較熟悉砌滞,通過 synchronized 關(guān)鍵字來實(shí)現(xiàn)侮邀;所有加上 synchronized 的方法和塊語(yǔ)句,在多線程訪問的時(shí)候贝润,同一時(shí)刻只能有一個(gè)線程能夠訪問绊茧。
wait()、notify()打掘、notifyAll()
這三個(gè)方法是 java.lang.Object 的 final native 方法华畏,任何繼承 java.lang.Object 的類都有這三個(gè)方法。它們是Java語(yǔ)言提供的實(shí)現(xiàn)線程間阻塞和控制進(jìn)程內(nèi)調(diào)度的底層機(jī)制胧卤,平時(shí)我們會(huì)很少用到的唯绍。
wait():
導(dǎo)致線程進(jìn)入等待狀態(tài),直到它被其他線程通過notify()或者notifyAll喚醒枝誊,該方法只能在同步方法中調(diào)用况芒。
notify():
隨機(jī)選擇一個(gè)在該對(duì)象上調(diào)用wait方法的線程,解除其阻塞狀態(tài),該方法只能在同步方法或同步塊內(nèi)部調(diào)用。
notifyAll():
解除所有那些在該對(duì)象上調(diào)用wait方法的線程的阻塞狀態(tài)宏所,同樣該方法只能在同步方法或同步塊內(nèi)部調(diào)用助析。
調(diào)用這三個(gè)方法中任意一個(gè),當(dāng)前線程必須是鎖的持有者丽蝎,如果不是會(huì)拋出一個(gè) IllegalMonitorStateException 異常。
wait() 與 Thread.sleep(long time) 的區(qū)別
sleep():在指定的毫秒數(shù)內(nèi)讓當(dāng)前正在執(zhí)行的線程休眠(暫停執(zhí)行),該線程不丟失任何監(jiān)視器的所屬權(quán)止剖,sleep() 是 Thread 類專屬的靜態(tài)方法,針對(duì)一個(gè)特定的線程落君。
wait() 方法使實(shí)體所處線程暫停執(zhí)行穿香,從而使對(duì)象進(jìn)入等待狀態(tài),直到被 notify() 方法通知或者 wait() 的等待的時(shí)間到绎速。sleep() 方法使持有的線程暫停運(yùn)行皮获,從而使線程進(jìn)入休眠狀態(tài),直到用 interrupt 方法來打斷他的休眠或者 sleep 的休眠的時(shí)間到纹冤。
wait() 方法進(jìn)入等待狀態(tài)時(shí)會(huì)釋放同步鎖洒宝,而 sleep() 方法不會(huì)釋放同步鎖购公。所以,當(dāng)一個(gè)線程無限 sleep 時(shí)又沒有任何人去 interrupt 它的時(shí)候雁歌,程序就產(chǎn)生大麻煩了宏浩,notify() 是用來通知線程,但在 notify() 之前線程是需要獲得 lock 的将宪。另個(gè)意思就是必須寫在 synchronized(lockobj) {...} 之中绘闷。wait() 也是這個(gè)樣子,一個(gè)線程需要釋放某個(gè) lock较坛,也是在其獲得 lock 情況下才能夠釋放印蔗,所以 wait() 也需要放在 synchronized(lockobj) {...} 之中。
volatile 關(guān)鍵字
volatile 是一個(gè)特殊的修飾符丑勤,只有成員變量才能使用它华嘹。在Java并發(fā)程序缺少同步類的情況下,多線程對(duì)成員變量的操作對(duì)其它線程是透明的法竞。volatile 變量可以保證下一個(gè)讀取操作會(huì)在前一個(gè)寫操作之后發(fā)生耙厚。線程都會(huì)直接從內(nèi)存中讀取該變量并且不緩存它。這就確保了線程讀取到的變量是同內(nèi)存中是一致的岔霸。
ThreadLocal 變量
ThreadLocal 是Java里一種特殊的變量薛躬。每個(gè)線程都有一個(gè) ThreadLocal 就是每個(gè)線程都擁有了自己獨(dú)立的一個(gè)變量,競(jìng)爭(zhēng)條件被徹底消除了呆细。如果為每個(gè)線程提供一個(gè)自己獨(dú)有的變量拷貝型宝,將大大提高效率。首先絮爷,通過復(fù)用減少了代價(jià)高昂的對(duì)象的創(chuàng)建個(gè)數(shù)趴酣。其次,你在沒有使用高代價(jià)的同步或者不變性的情況下獲得了線程安全坑夯。
join() 方法
join() 方法定義在 Thread 類中岖寞,所以調(diào)用者必須是一個(gè)線程,join() 方法主要是讓調(diào)用該方法的 Thread 完成 run() 方法里面的東西后柜蜈,再執(zhí)行 join() 方法后面的代碼仗谆,看下下面的"意思"代碼:
啟動(dòng) t1 后,調(diào)用了 join() 方法淑履,直到 t1 的計(jì)數(shù)任務(wù)結(jié)束胸私,才輪到 t2 啟動(dòng),然后 t2 才開始計(jì)數(shù)任務(wù)鳖谈,兩個(gè)線程是按著嚴(yán)格的順序來執(zhí)行的。如果 t2 的執(zhí)行需要依賴于 t1 中的完整數(shù)據(jù)的時(shí)候阔涉,這種方法就可以很好的確保兩個(gè)線程的同步性缆娃。
Thread.yield() 方法
Thread.sleep(long time):線程暫時(shí)終止執(zhí)行(睡眠)一定的時(shí)間捷绒。
Thread.yield():線程放棄運(yùn)行,將CPU的控制權(quán)讓出贯要。
這兩個(gè)方法都會(huì)將當(dāng)前運(yùn)行線程的CPU控制權(quán)讓出來暖侨,但 sleep() 方法在指定的睡眠時(shí)間內(nèi)一定不會(huì)再得到運(yùn)行機(jī)會(huì),直到它的睡眠時(shí)間完成崇渗;而 yield() 方法讓出控制權(quán)后字逗,還有可能馬上被系統(tǒng)的調(diào)度機(jī)制選中來運(yùn)行,比如宅广,執(zhí)行yield()方法的線程優(yōu)先級(jí)高于其他的線程葫掉,那么這個(gè)線程即使執(zhí)行了 yield() 方法也可能不能起到讓出CPU控制權(quán)的效果,因?yàn)樗尦隹刂茩?quán)后跟狱,進(jìn)入排隊(duì)隊(duì)列俭厚,調(diào)度機(jī)制將從等待運(yùn)行的線程隊(duì)列中選出一個(gè)等級(jí)最高的線程來運(yùn)行,那么它又(很可能)被選中來運(yùn)行驶臊。
擴(kuò)展
線程調(diào)度策略
(1) 搶占式調(diào)度策略
Java運(yùn)行時(shí)系統(tǒng)的線程調(diào)度算法是搶占式的挪挤。Java運(yùn)行時(shí)系統(tǒng)支持一種簡(jiǎn)單的固定優(yōu)先級(jí)的調(diào)度算法。如果一個(gè)優(yōu)先級(jí)比其他任何處于可運(yùn)行狀態(tài)的線程都高的線程進(jìn)入就緒狀態(tài)关翎,那么運(yùn)行時(shí)系統(tǒng)就會(huì)選擇該線程運(yùn)行扛门。新的優(yōu)先級(jí)較高的線程搶占了其他線程。但是Java運(yùn)行時(shí)系統(tǒng)并不搶占同優(yōu)先級(jí)的線程纵寝。換句話說论寨,Java運(yùn)行時(shí)系統(tǒng)不是分時(shí)的。然而店雅,基于Java Thread類的實(shí)現(xiàn)系統(tǒng)可能是支持分時(shí)的政基,因此編寫代碼時(shí)不要依賴分時(shí)。當(dāng)系統(tǒng)中的處于就緒狀態(tài)的線程都具有相同優(yōu)先級(jí)時(shí)闹啦,線程調(diào)度程序采用一種簡(jiǎn)單的沮明、非搶占式的輪轉(zhuǎn)的調(diào)度順序。
(2) 時(shí)間片輪轉(zhuǎn)調(diào)度策略
有些系統(tǒng)的線程調(diào)度采用時(shí)間片輪轉(zhuǎn)調(diào)度策略窍奋。這種調(diào)度策略是從所有處于就緒狀態(tài)的線程中選擇優(yōu)先級(jí)最高的線程分配一定的CPU時(shí)間運(yùn)行荐健。該時(shí)間過后再選擇其他線程運(yùn)行。只有當(dāng)線程運(yùn)行結(jié)束琳袄、放棄(yield)CPU或由于某種原因進(jìn)入阻塞狀態(tài)江场,低優(yōu)先級(jí)的線程才有機(jī)會(huì)執(zhí)行。如果有兩個(gè)優(yōu)先級(jí)相同的線程都在等待CPU窖逗,則調(diào)度程序以輪轉(zhuǎn)的方式選擇運(yùn)行的線程址否。
● 線程池
創(chuàng)建多個(gè)線程不光麻煩而且相對(duì)影響系統(tǒng)性能,接下來讓我看看使用線程池來操作多線程碎紊。
線程池的優(yōu)點(diǎn)
1)避免線程的創(chuàng)建和銷毀帶來的性能開銷佑附。
2)避免大量的線程間因互相搶占系統(tǒng)資源導(dǎo)致的阻塞現(xiàn)象樊诺。
3}能夠?qū)€程進(jìn)行簡(jiǎn)單的管理并提供定時(shí)執(zhí)行、間隔執(zhí)行等功能音同。
再擼一擼概念
Java里面線程池的頂級(jí)接口是 Executor词爬,不過真正的線程池接口是 ExecutorService, ExecutorService 的默認(rèn)實(shí)現(xiàn)是 ThreadPoolExecutor权均;普通類 Executors 里面調(diào)用的就是 ThreadPoolExecutor顿膨。
照例看一下各個(gè)接口的源碼:
下面我創(chuàng)建的一個(gè)線程池:
Executors 提供四種線程池:
1)newCachedThreadPool 是一個(gè)可根據(jù)需要?jiǎng)?chuàng)建新線程的線程池,但是在以前構(gòu)造的線程可用時(shí)將重用它們叽赊。對(duì)于執(zhí)行很多短期異步任務(wù)的程序而言恋沃,這些線程池通常可提高程序性能蛇尚。調(diào)用 execute() 將重用以前構(gòu)造的線程(如果線程可用)芽唇。如果現(xiàn)有線程沒有可用的,則創(chuàng)建一個(gè)新線程并添加到池中取劫。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程匆笤。因此,長(zhǎng)時(shí)間保持空閑的線程池不會(huì)使用任何資源谱邪。注意炮捧,可以使用 ThreadPoolExecutor 構(gòu)造方法創(chuàng)建具有類似屬性但細(xì)節(jié)不同(例如超時(shí)參數(shù))的線程池。
2)newSingleThreadExecutor 創(chuàng)建是一個(gè)單線程池惦银,也就是該線程池只有一個(gè)線程在工作咆课,所有的任務(wù)是串行執(zhí)行的,如果這個(gè)唯一的線程因?yàn)楫惓=Y(jié)束扯俱,那么會(huì)有一個(gè)新的線程來替代它书蚪,此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行。
3)newFixedThreadPool 創(chuàng)建固定大小的線程池迅栅,每次提交一個(gè)任務(wù)就創(chuàng)建一個(gè)線程殊校,直到線程達(dá)到線程池的最大大小,線程池的大小一旦達(dá)到最大值就會(huì)保持不變读存,如果某個(gè)線程因?yàn)閳?zhí)行異常而結(jié)束为流,那么線程池會(huì)補(bǔ)充一個(gè)新線程。
4)newScheduledThreadPool 創(chuàng)建一個(gè)大小無限的線程池让簿,此線程池支持定時(shí)以及周期性執(zhí)行任務(wù)的需求敬察。
通過 ThreadPoolExecutor 的構(gòu)造函數(shù),擼一擼線程池相關(guān)參數(shù)的概念:
1)corePoolSize:線程池的核心線程數(shù)尔当,一般情況下不管有沒有任務(wù)都會(huì)一直在線程池中一直存活莲祸,只有在 ThreadPoolExecutor 中的方法 allowCoreThreadTimeOut(boolean value) 設(shè)置為 true 時(shí),閑置的核心線程會(huì)存在超時(shí)機(jī)制,如果在指定時(shí)間沒有新任務(wù)來時(shí)虫给,核心線程也會(huì)被終止藤抡,而這個(gè)時(shí)間間隔由第3個(gè)屬性 keepAliveTime 指定。
2)maximumPoolSize:線程池所能容納的最大線程數(shù)抹估,當(dāng)活動(dòng)的線程數(shù)達(dá)到這個(gè)值后,后續(xù)的新任務(wù)將會(huì)被阻塞弄兜。
3)keepAliveTime:控制線程閑置時(shí)的超時(shí)時(shí)長(zhǎng)药蜻,超過則終止該線程。一般情況下用于非核心線程替饿,只有在 ThreadPoolExecutor 中的方法 allowCoreThreadTimeOut(boolean value) 設(shè)置為 true時(shí)语泽,也作用于核心線程。
4)unit:用于指定 keepAliveTime 參數(shù)的時(shí)間單位视卢,TimeUnit 是個(gè) enum 枚舉類型踱卵,常用的有:TimeUnit.HOURS(小時(shí))、TimeUnit.MINUTES(分鐘)据过、TimeUnit.SECONDS(秒) 和 TimeUnit.MILLISECONDS(毫秒)等惋砂。
5)workQueue:線程池的任務(wù)隊(duì)列,通過線程池的 execute(Runnable command) 方法會(huì)將任務(wù) Runnable 存儲(chǔ)在隊(duì)列中绳锅。
6)threadFactory:線程工廠西饵,它是一個(gè)接口,用來為線程池創(chuàng)建新線程的鳞芙。
線程池的關(guān)閉
ThreadPoolExecutor 提供了兩個(gè)方法眷柔,用于線程池的關(guān)閉,分別是 shutdown() 和 shutdownNow()原朝。
shutdown():不會(huì)立即的終止線程池,而是要等所有任務(wù)緩存隊(duì)列中的任務(wù)都執(zhí)行完后才終止鞠评,但再也不會(huì)接受新的任務(wù)锥忿。
shutdownNow():立即終止線程池,并嘗試打斷正在執(zhí)行的任務(wù),并且清空任務(wù)緩存隊(duì)列,返回尚未執(zhí)行的任務(wù)诊杆。
小編推薦一個(gè)學(xué)Java的學(xué)習(xí)裙【 六五零,五五四,六零七 】,無論你是大牛還是小白镊尺,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)弄砍!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享!
面試題
1)什么是 Executor 框架婶博?
Executor框架在Java 5中被引入搭综,Executor 框架是一個(gè)根據(jù)一組執(zhí)行策略調(diào)用、調(diào)度划栓、執(zhí)行和控制的異步任務(wù)的框架。
無限制的創(chuàng)建線程會(huì)引起應(yīng)用程序內(nèi)存溢出条获,所以創(chuàng)建一個(gè)線程池是個(gè)更好的的解決方案忠荞,因?yàn)榭梢韵拗凭€程的數(shù)量并且可以回收再利用這些線程。利用 Executor 框架可以非常方便的創(chuàng)建一個(gè)線程池帅掘。
2)Executors 類是什么委煤?
Executors為Executor、ExecutorService修档、ScheduledExecutorService碧绞、ThreadFactory 和 Callable 類提供了一些工具方法。Executors 可以用于方便的創(chuàng)建線程池