更新時(shí)間:2020-04-01 14:16:30 來源:動(dòng)力節(jié)點(diǎn) 瀏覽2856次
什么是線程?
線程是輕量級進(jìn)程(process)。 任何進(jìn)程(process)都可以在其中運(yùn)行多個(gè)線程。
例如,在Web瀏覽器中,我們可以有一個(gè)線程將加載用戶界面,而我們可以有另一個(gè)線程實(shí)際上將檢索需要在用戶界面中顯示的所有數(shù)據(jù)。
什么是多線程
多線程使我們能夠同時(shí)運(yùn)行多個(gè)線程。
例如,在Web瀏覽器中,我們可以有一個(gè)處理用戶界面的線程,同時(shí),我們可以有另一個(gè)線程來獲取要顯示的數(shù)據(jù)。
因此,多線程改善了系統(tǒng)的響應(yīng)能力。
什么是并發(fā)
線程上下文中的并發(fā)性使我們可以同時(shí)運(yùn)行多個(gè)線程。
但是線程真的在同時(shí)運(yùn)行嗎?
單核系統(tǒng)
JVM提供的線程調(diào)度程序(Thread Scheduler)決定在任何給定時(shí)間運(yùn)行哪個(gè)線程。 調(diào)度程序給每個(gè)線程一段非常小的時(shí)間運(yùn)行。
因此,在任何給定時(shí)間,我們只有一個(gè)在處理器中實(shí)際運(yùn)行的線程。 但是由于切換時(shí)間間隔非常小,我們感覺到多個(gè)線程正在同時(shí)運(yùn)行。
多核系統(tǒng)
即使在多核系統(tǒng)中,也要使用線程調(diào)度程序。 但是,由于我們有多個(gè)內(nèi)核,因此實(shí)際上我們可以在相同時(shí)間運(yùn)行多個(gè)線程。
例如,如果我們有一個(gè)雙核系統(tǒng),那么我們可以有兩個(gè)線程同時(shí)運(yùn)行。 第一個(gè)線程將在第一個(gè)內(nèi)核中運(yùn)行,第二個(gè)線程將在第二個(gè)內(nèi)核中運(yùn)行。
為什么需要多線程?
多線程使我們能夠改善系統(tǒng)的響應(yīng)能力。
例如,在Web瀏覽器中,如果所有內(nèi)容都在單個(gè)Thread中運(yùn)行,則每當(dāng)獲取數(shù)據(jù)以進(jìn)行顯示時(shí),系統(tǒng)將完全不響應(yīng)。 如果需要10秒鐘來獲取數(shù)據(jù),那么在那10秒鐘內(nèi),我們將無法在網(wǎng)絡(luò)瀏覽器中執(zhí)行任何其他操作,例如打開新標(biāo)簽頁,甚至關(guān)閉瀏覽器。
因此,在不同線程中同時(shí)運(yùn)行程序的不同部分有助于提高系統(tǒng)的響應(yīng)能力。
如何用Java編寫多線程程序
我們可以使用以下方法在Java中創(chuàng)建線程
繼承Thread類
實(shí)施Runnable接口
實(shí)施Callable接口
通過Executor框架與Runnable和Callable任務(wù)一起使用
我將在下期穩(wěn)重中介紹Callables和Executor框架。 在本文中,我將主要集中于繼承Thread類和實(shí)現(xiàn)Runnable接口。
繼承Thread類
為了創(chuàng)建可以在Thread中運(yùn)行的代碼,我們創(chuàng)建一個(gè)類,然后繼承Thread類。 任務(wù)代碼需要放在run()函數(shù)中。 在下面的代碼中,您可以看到Worker是擴(kuò)展Thread Class的類,并且在run()函數(shù)內(nèi)部完成了打印數(shù)字0至5的任務(wù)。

在上面的代碼中,Thread.currentThread().getName()用于獲取運(yùn)行代碼的當(dāng)前線程的名稱。
為了創(chuàng)建一個(gè)線程,我們只需要?jiǎng)?chuàng)建一個(gè)Worker類的實(shí)例。 然后,我們可以使用start()函數(shù)啟動(dòng)線程。

在上述代碼中,我們從Worker類創(chuàng)建3個(gè)線程t1,t2和t3。
然后,我們使用start()方法啟動(dòng)線程。
下圖是通過擴(kuò)展Thread類創(chuàng)建線程的全部代碼。

這是我們通過運(yùn)行上面的代碼獲得的輸出
可以看出,所有3個(gè)線程都已打印從0到5的數(shù)字。
從輸出中可以清楚地看到3個(gè)線程沒有按任何特定順序運(yùn)行。
實(shí)現(xiàn)Runnable接口
為了創(chuàng)建可以在線程中運(yùn)行的代碼,我們創(chuàng)建一個(gè)類,然后實(shí)現(xiàn)Runnable接口。 由這段代碼完成的任務(wù)需要放在run()函數(shù)中。 在下面的代碼中,您可以看到RunnableWorker是實(shí)現(xiàn)Runnable接口的類,并且打印數(shù)字0到4的任務(wù)是在run()函數(shù)中完成的。
為了創(chuàng)建線程,首先我們需要?jiǎng)?chuàng)建一個(gè)RunnableWorker對象,該對象實(shí)現(xiàn)Runnable接口。
然后,我們可以通過創(chuàng)建Thread類的對象并將RunnableWorker的對象作為參數(shù)傳遞來創(chuàng)建新線程。 如下面的代碼所示。
上面的代碼創(chuàng)建了一個(gè)Runnable對象r。 然后,它創(chuàng)建3個(gè)線程t1,t2和t3,并將r作為參數(shù)傳遞給3個(gè)線程。 然后使用start()函數(shù)啟動(dòng)所有3個(gè)線程。
下圖為通過實(shí)現(xiàn)Runnable接口創(chuàng)建線程的完整代碼
在運(yùn)行上述代碼時(shí),我們將獲得以下輸出。 每次運(yùn)行代碼時(shí),輸出順序都會改變。
與繼承Thread類相比,實(shí)現(xiàn)Runnable接口是更好的選擇,因?yàn)槲覀冎荒芾^承一個(gè)類,但是我們可以在java中實(shí)現(xiàn)多個(gè)接口。
Java 8中的Runnable接口
在Java 8中,由于Runnable接口只有一個(gè)方法run(),因此它成為FunctionalInterface(函數(shù)式接口)。
以下代碼顯示了我們?nèi)绾卧贘ava 8中創(chuàng)建可運(yùn)行實(shí)例,并且使用了Lambda。
在這里,無需創(chuàng)建類然后實(shí)現(xiàn)Runnable接口,我們可以直接使用lambda表達(dá)式創(chuàng)建Runnable實(shí)例,如下所示
以上就是動(dòng)力節(jié)點(diǎn)java培訓(xùn)機(jī)構(gòu)的小編針對“Java基礎(chǔ)學(xué)習(xí):java多線程視頻”的內(nèi)容進(jìn)行的回答,希望對大家有所幫助,如有疑問,請?jiān)诰€咨詢,有專業(yè)老師隨時(shí)為你服務(wù)。
相關(guān)閱讀

初級 202925

初級 203221

初級 202629

初級 203743