Java創(chuàng)建線程的七種方法總結(jié)(全網(wǎng)最全面)
前言
屬于基礎(chǔ)的面試問題,一定要能夠回答全哦~
一、繼承Thread,重寫run方法
通過自定義一個類(這里起名為:MyThread),繼承Thread類,重寫run方法,最后在main方法中new出MyThread實例,調(diào)用這個實例的繼承的Thread類的start方法創(chuàng)建一個線程。
Ps:
1.創(chuàng)建出MyThread實例,并不代表在系統(tǒng)真的創(chuàng)建一個線程,只有調(diào)用start方法時,才創(chuàng)建出一個新的線程,新線程會執(zhí)行run里的邏輯,直到run里邏輯執(zhí)行完,線程就結(jié)束了;
2.運行一次Java程序就啟動了一個進程,一個進程里至少會有一個線程,這里JVM默認創(chuàng)建的線程就是main線程(主線程),main主線程和MyThread創(chuàng)建出來的新線程是“并發(fā)執(zhí)行”的關(guān)系(并發(fā)+并行),也可以理解為同時執(zhí)行,各執(zhí)行各的;
3.直接調(diào)用run并沒有創(chuàng)建線程,只是在原來的線程中執(zhí)行代碼;
代碼如下:
class MyThread extends Thread { @Override public void run() { System.out.println("繼承Thread,重寫run方法創(chuàng)建線程"); } } public class Main { public static void main(String[] args) { MyThread myThread = new MyThread(); myThread.start(); } }
二、實現(xiàn)Runnable接口,重寫run方法
通過自定義一個類(這里起名為:MyRunnable)實現(xiàn)Runnable接口,重寫run方法,最后在main方法new出MyRunnable實例和Thread實例,最后通過start方法創(chuàng)建并啟動線程。
通俗理解:
這里相當于把線程要干的活和線程本身分離開了,使用MyRunnable這個自定義的類來表示“線程要完成的任務(wù)”,這樣做的目的就是為了“解耦合”,假設(shè)未來有新的任務(wù)需要線程去執(zhí)行,那么通過這種方式,代碼改動就比較小。
代碼如下:
class MyRunnable implements Runnable { @Override public void run() { System.out.println("實現(xiàn)Runnable接口,重寫run方法"); } } public class Main { public static void main(String[] args) { MyRunnable myRunnable = new MyRunnable(); Thread thread = new Thread(myRunnable); thread.start(); } }
三、使用匿名內(nèi)部類創(chuàng)建 Thread 子類對象
直接創(chuàng)建Thread子類,同時實例化出一個對象,重寫run方法,最后通過start方法創(chuàng)建并啟動線程。
代碼如下:
public class Main { public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { System.out.println("使用匿名內(nèi)部類創(chuàng)建 Thread 子類對象"); } }; thread.start(); } }
四、使用匿名內(nèi)部類,實現(xiàn)Runnable接口
通過使用使用匿名內(nèi)部類,實現(xiàn)Runnable接口作為Thread構(gòu)造方法的參數(shù),最后通過start創(chuàng)建并啟動線程;
代碼如下:
public class Main { public static void main(String[] args) { Thread thread = new Thread(new Runnable() { @Override public void run() { System.out.println("使用匿名內(nèi)部類,實例Runnable接口作為構(gòu)造參數(shù)"); } }); thread.start(); } }
五、lambda表達式
lambda本質(zhì)上就是一個“匿名函數(shù)”,()表示函數(shù)的形參,{}表示函數(shù)體,->特殊語法,表示它是lambda表達式(->是從C++那里抄來的)。
代碼如下:
public class Main { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("使用lambda表示創(chuàng)建線程"); }); thread.start(); } }
六、實現(xiàn)Callable接口
通過自定義類(這里起名為:MyCallable),實現(xiàn)Callable接口,重寫call方法(call方法可以理解為線程需要執(zhí)行的任務(wù)),并且?guī)в蟹祷刂?,這個返回表示一個計算結(jié)果,如果無法計算結(jié)果,則引發(fā)Exception異常,如下源碼英文解釋:
接著創(chuàng)建Callable實例,使用FutrueTast類包裝Callable對象,F(xiàn)utureTask是一個包裝器,需要接收Callable實例來創(chuàng)建,并且有兩個構(gòu)造函數(shù),一個參數(shù)只有Callable對象,另一個參數(shù)不僅有Callable對象,還有一個泛型的result參數(shù),詳細解釋如下源碼:
最后使用FutureTask對象作為Thread的構(gòu)造參數(shù),通過start方法創(chuàng)建并啟動線程;
注意:這里可以用get方法獲取線程執(zhí)行后的返回值。
代碼如下:
class MyCallableTest implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("創(chuàng)建線程:" + Thread.currentThread().getName()); return 2; } } public class Main { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<Integer> task = new FutureTask<>(new MyCallableTest()); Thread thread = new Thread(task); thread.start(); System.out.println("創(chuàng)建線程的返回結(jié)果為:" + task.get()); } }
七、使用線程池創(chuàng)建線程
在Java中,線程池的本體叫ThreadPoolExecutor,他的構(gòu)造方法寫起來十分麻煩,為了簡化構(gòu)造方法,標準庫就提供了一系列工廠方法,簡化使用;
什么是工廠模式?
工廠模式,將創(chuàng)建產(chǎn)品實例的權(quán)利移交工廠,我們不再通過new來創(chuàng)建我們所需的對象,而是通過工廠來獲取我們需要的產(chǎn)品。降低了產(chǎn)品使用者與使用者之間的耦合關(guān)系;
也就是說這里創(chuàng)建線程池沒有顯式new,而是通過Executors這個靜態(tài)方法newCaChedThreadPool來完成的;
常見用法:
線程池的單純使用很簡單,使用submit方法,把任務(wù)提交到線程池中即可,線程池中會有線程來完成這些任務(wù);
代碼如下:
import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class Pool { public static void main(String[] args) { ExecutorService pool = Executors.newCachedThreadPool(); pool.submit(new Runnable() { @Override public void run() { //執(zhí)行業(yè)務(wù)邏輯 for(int i = 1; i <= 100; i++) { System.out.println("線程:" + Thread.currentThread().getName() + "執(zhí)行了任務(wù)" + i + "~"); } } }); pool.submit(new Runnable() { @Override public void run() { //執(zhí)行業(yè)務(wù)邏輯 for(int i = 101; i <= 200; i++) { System.out.println("線程:" + Thread.currentThread().getName() + "執(zhí)行了任務(wù)" + i + "~"); } } }); pool.submit(new Runnable() { @Override public void run() { //執(zhí)行業(yè)務(wù)邏輯 for(int i = 201; i <= 300; i++) { System.out.println("線程:" + Thread.currentThread().getName() + "執(zhí)行了任務(wù)" + i + "~"); } } }); } }
當任務(wù)量達到一定程度,一個線程忙不過來時,就會發(fā)現(xiàn)其他線程也來幫忙遼~
總結(jié)
到此這篇關(guān)于Java創(chuàng)建線程的七種方法總結(jié)的文章就介紹到這了,更多相關(guān)Java創(chuàng)建線程方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用實戰(zhàn)
這篇文章主要介紹了java枚舉類的屬性、方法和構(gòu)造方法應(yīng)用,結(jié)合實例形式分析了java枚舉類的定義、構(gòu)造及相關(guān)應(yīng)用操作技巧,需要的朋友可以參考下2019-08-08IDEA 2020.1 搜索不到Chinese (Simplified) Language
小編在安裝中文插件時遇到IDEA 2020.1 搜索不到Chinese ​(Simplified)​ Language Pack EAP,無法安裝的問題,本文給大家分享我的解決方法,感興趣的朋友一起看看吧2020-04-04MyBatis使用annonation定義類型映射的簡易用法示例
這篇文章主要介紹了MyBatis使用annonation定義類型映射的簡易用法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-09-09Java中main函數(shù)的String[]?args用法舉例詳解
這篇文章主要給大家介紹了關(guān)于Java中main函數(shù)的String[]?args用法的相關(guān)資料,JAVA類中main函數(shù)的參數(shù)String[]?args指的是運行時給main函數(shù)傳遞的參數(shù),文中通過圖文以及代碼介紹的非常詳細,需要的朋友可以參考下2023-12-12