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

