Java中實(shí)現(xiàn)多線程的幾種方式總結(jié)
Java實(shí)現(xiàn)多線程的幾種方式
1)繼承Thread類
實(shí)現(xiàn)的步驟:
- 1)創(chuàng)建Thread類的子類
- 2)重寫run方法
- 3)創(chuàng)建線程對象
- 4)啟動線程
代碼示例:
package com.bobo.thread; public class ThreadDemo02 { /** * 線程的第一種實(shí)現(xiàn)方式 * 通過創(chuàng)建Thread類的子類來實(shí)現(xiàn) * @param args */ public static void main(String[] args) { System.out.println("main方法執(zhí)行了1..."); // Java中的線程 本質(zhì)上就是一個(gè)Thread對象 Thread t1 = new ThreadTest01(); // 啟動一個(gè)新的線程 t1.start(); for(int i = 0 ; i< 100 ; i++){ System.out.println("main方法的循環(huán)..."+i); } System.out.println("main方法執(zhí)行結(jié)束了3..."); } }
/** * 第一個(gè)自定義的線程類 * 繼承Thread父類 * 重寫run方法 */ class ThreadTest01 extends Thread{ @Override public void run() { System.out.println("我們的第一個(gè)線程執(zhí)行了2...."); for(int i = 0 ; i < 10 ; i ++){ System.out.println("子線程:"+i); } } }
注意點(diǎn):
1)啟動線程是使用start方法而不是run方法
2)線程不能啟動多次,如果要創(chuàng)建多個(gè)線程,那么就需要創(chuàng)建多個(gè)Thread對象
2)實(shí)現(xiàn)Runnable接口
在第一種實(shí)現(xiàn)方式中,我們是將線程的創(chuàng)建和線程執(zhí)行的業(yè)務(wù)都封裝在了Thread對象中,我們可以通過Runable接口來實(shí)現(xiàn)線程程序代碼和數(shù)據(jù)有效的分離。
實(shí)現(xiàn)的步驟:
- 1)創(chuàng)建Runable的實(shí)現(xiàn)類
- 2)重寫run方法
- 3)創(chuàng)建Runable實(shí)例對象(通過實(shí)現(xiàn)類來實(shí)現(xiàn))
- 4)創(chuàng)建Thread對象,并把第三步創(chuàng)建的Runable實(shí)例作為Thread構(gòu)造方法的參數(shù)
- 5)啟動線程
代碼示例:
package com.bobo.runable; public class RunableDemo01 { /** * 線程的第二種方式 * 本質(zhì)是創(chuàng)建Thread對象的時(shí)候傳遞了一個(gè)Runable接口實(shí)現(xiàn) * @param args */ public static void main(String[] args) { System.out.println("main執(zhí)行了..."); // 創(chuàng)建一個(gè)新的線程 Thread對象 Runnable r1 = new RunableTest(); Thread t1 = new Thread(r1); // 啟動線程 t1.start(); System.out.println("main結(jié)束了..."); } } /** * 線程的第二種創(chuàng)建方式 * 創(chuàng)建一個(gè)Runable接口的實(shí)現(xiàn)類 */ class RunableTest implements Runnable{ @Override public void run() { System.out.println("子線程執(zhí)行了..."); } }
實(shí)現(xiàn)Runable接口的好處:
1)可以避免Java單繼承帶來的局限性
2)適合多個(gè)相同的程序代碼處理同一個(gè)資源的情況,把線程同程序的代碼和數(shù)據(jù)有效的分離,較好的體現(xiàn)了面向?qū)ο蟮脑O(shè)計(jì)思想
3)實(shí)現(xiàn)Callable接口(JDK1.5>=)
前面我們介紹的兩種創(chuàng)建線程的方式都是重寫run方法,而且run方法是沒有返回結(jié)果的,也就是main方法是不知道開啟的線程什么時(shí)候開始執(zhí)行,什么時(shí)候結(jié)束執(zhí)行,也獲取不到對應(yīng)的返回結(jié)果。而且run方法也不能把可能產(chǎn)生的異常拋出。
在JDK1.5之后推出了通過實(shí)現(xiàn)Callable接口的方式來創(chuàng)建新的線程,這種方式可以獲取對應(yīng)的返回結(jié)果。
代碼示例:
package com.bobo.callable; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; public class CallableDemo01 { /** * 創(chuàng)建線程的第三種實(shí)現(xiàn)方式: * Callable方式 */ public static void main(String[] args) throws Exception { // 創(chuàng)建一個(gè)Callable實(shí)例 Callable<Integer> callable = new MyCallable(); FutureTask<Integer> futureTask = new FutureTask<>(callable); // 獲取一個(gè)線程 肯定是要先創(chuàng)建一個(gè)Thread對象 futureTask本質(zhì)上是Runable接口的實(shí)現(xiàn) Thread t1 = new Thread(futureTask); System.out.println("main方法start...."); t1.start(); // 本質(zhì)還是執(zhí)行的 Runable中的run方法,只是 run方法調(diào)用了call方法罷了 // 獲取返回的結(jié)果 System.out.println(futureTask.get()); // 獲取開啟的線程執(zhí)行完成后返回的結(jié)果 System.out.println("main方法end ...."); } } /** * 創(chuàng)建Callable的實(shí)現(xiàn)類 * 我們需要指定Callable的泛型,這個(gè)泛型是返回結(jié)果的類型 */ class MyCallable implements Callable<Integer>{ /** * 線程自動后會執(zhí)行的方法 * @return * @throws Exception */ @Override public Integer call() throws Exception { int sum = 0; for(int i = 1 ; i <= 100 ; i ++){ sum += i; } return sum; } }
實(shí)現(xiàn)Runnable接口和實(shí)現(xiàn)Callable接口的區(qū)別:
- 1)Runnable是自從java1.1就有了,而Callable是1.5之后才加上去的
- 2)Callable規(guī)定的方法是call(),Runnable規(guī)定的方法是run()
- 3)Callable的任務(wù)執(zhí)行后可返回值,而Runnable的任務(wù)是不能返回值(是void)
- 4)call方法可以拋出異常,run方法不可以
- 5)運(yùn)行Callable任務(wù)可以拿到一個(gè)Future對象,表示異步計(jì)算的結(jié)果。它提供了檢查計(jì)算是否完成的方法,以等待計(jì)算的完成,并檢索計(jì)算的結(jié)果。通過Future對象可以了解任務(wù)執(zhí)行情況,可取消任務(wù)的執(zhí)行,還可獲取執(zhí)行結(jié)果。
4)線程池方式創(chuàng)建
加入線程池運(yùn)行,Runnable使用ExecutorService的execute方法,Callable使用submit方法。
其實(shí)Callable接口底層的實(shí)現(xiàn)就是對Runable接口實(shí)現(xiàn)的封裝,線程啟動執(zhí)行的也是Runable接口實(shí)現(xiàn)中的run方法,只是在run方法中有調(diào)用call方法罷了
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java嵌套for循環(huán)的幾種常見優(yōu)化方案
這篇文章主要給大家介紹了關(guān)于Java嵌套for循環(huán)的幾種常見優(yōu)化,在Java中優(yōu)化嵌套for循環(huán)可以通過以下幾種方式來提高性能和效率,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-07-07Java中的Set接口實(shí)現(xiàn)類HashSet和LinkedHashSet詳解
這篇文章主要介紹了Java中的Set接口實(shí)現(xiàn)類HashSet和LinkedHashSet詳解,Set接口和java.util.List接口一樣,同樣繼承自Collection接口,它與Collection接口中的方法基本一致,并沒有對Collection接口進(jìn)行功能上的擴(kuò)充,只是比Collection接口更加嚴(yán)格了,需要的朋友可以參考下2024-01-01eclipse/IDEA配置javafx項(xiàng)目步驟(圖文教程)
這篇文章主要介紹了eclipse/IDEA配置javafx項(xiàng)目步驟(圖文教程),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03詳解Mybatis中javaType和ofType的區(qū)別
本文主要介紹了詳解Mybatis中javaType和ofType的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-05-05Eclipse中安裝反編譯工具Fernflower的方法(Enhanced Class Decompiler)
這篇文章主要介紹了Eclipse中安裝反編譯工具Fernflower的方法(Enhanced Class Decompiler),本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01MyBatis中RowBounds實(shí)現(xiàn)內(nèi)存分頁
RowBounds是MyBatis提供的一種內(nèi)存分頁方式,適用于小數(shù)據(jù)量的分頁場景,本文就來詳細(xì)的介紹一下,具有一定的參考價(jià)值,感興趣的可以了解一下2024-12-12