Thread、Runable和Callable 三者區(qū)別?Thread 是一個(gè)抽象類(lèi),只能被繼承,而 Runable、Callable 是接口,需要實(shí)現(xiàn)接口中的方法。繼承 Thread 重寫(xiě)run()方法,實(shí)現(xiàn)Runable接口需要實(shí)現(xiàn)run()方法,而Callable是需要實(shí)現(xiàn)call()方法。Thread 和 Runable 沒(méi)有返回值,Callable 有返回值,返回值可以被 Future 拿到。實(shí)現(xiàn) Runable 接口的類(lèi)不能直接調(diào)用start()方法,需要 new 一個(gè) Thread 并發(fā)該實(shí)現(xiàn)類(lèi)放入 Thread,再通過(guò)新建的 Thread 實(shí)例來(lái)調(diào)用start()方法。實(shí)現(xiàn) Callable 接口的類(lèi)需要借助 FutureTask (將該實(shí)現(xiàn)類(lèi)放入其中),再將 FutureTask 實(shí)例放入 Thread,再通過(guò)新建的 Thread 實(shí)例來(lái)調(diào)用start()方法。獲取返回值只需要借助 FutureTask 實(shí)例調(diào)用get()方法即可!什么是 FutureTask?FutureTask 表示一個(gè)異步運(yùn)算的任務(wù)。FutureTask 里面可以傳入一個(gè)Callable 的具體實(shí)現(xiàn)類(lèi),可以對(duì)這個(gè)異步運(yùn)算的任務(wù)的結(jié)果進(jìn)行等待獲取、判斷是否已經(jīng)完成、取消任務(wù)等操作。只有當(dāng)運(yùn)算完成的時(shí)候結(jié)果才能取回,如果運(yùn)算尚未完成 get 方法將會(huì)阻塞。一個(gè) FutureTask 對(duì)象可以對(duì)調(diào)用了 Callable 和 Runnable 的對(duì)象進(jìn)行包裝,由于 FutureTask 也是Runnable 接口的實(shí)現(xiàn)類(lèi),所以 FutureTask 也可以放入線程池中。
線程的 run()和 start()有什么區(qū)別?通過(guò)調(diào)用 Thread 類(lèi)的 start()方法來(lái)啟動(dòng)一個(gè)線程, 這時(shí)此線程是處于就緒狀態(tài), 并沒(méi)有運(yùn)行。這時(shí)無(wú)需等待 run 方法體代碼執(zhí)行完畢,可以直接繼續(xù)執(zhí)行下面的代碼。
方法 run()稱(chēng)為線程體,它包含了要執(zhí)行的這個(gè)線程的內(nèi)容,線程就進(jìn)入了運(yùn)行狀態(tài),開(kāi)始運(yùn)行 run 函數(shù)當(dāng)中的代碼。 run 方法運(yùn)行結(jié)束, 此線程終止。然后 CPU 再調(diào)度其它線程。
run() 可以重復(fù)調(diào)用,而 start()只能調(diào)用一次。
為什么我們調(diào)用 start() 方法時(shí)會(huì)執(zhí)行 run() 方法,為什么我們不能直接調(diào)用run() 方法?
如果直接執(zhí)行 run() 方法,會(huì)把 run 方法當(dāng)成一個(gè) main 線程下的普通方法去執(zhí)行,并不會(huì)在某個(gè)線程中執(zhí)行它,所以這并不是多線程工作。調(diào)用 start 方法方可啟動(dòng)線程并使線程進(jìn)入就緒狀態(tài),而 run 方法只是 thread 的一個(gè)普通方法調(diào)用,還是在主線程里執(zhí)行。
尚學(xué)堂給同學(xué)們帶來(lái)全新的Java300集課程啦!java零基礎(chǔ)小白自學(xué)Java必備優(yōu)質(zhì)教程_手把手圖解學(xué)習(xí)Java,讓學(xué)習(xí)成為一種享受_嗶哩嗶哩_bilibili