Java中實(shí)現(xiàn)多線程的幾種方式總結(jié)
Java實(shí)現(xiàn)多線程的幾種方式
1)繼承Thread類
實(shí)現(xiàn)的步驟:
- 1)創(chuàng)建Thread類的子類
- 2)重寫run方法
- 3)創(chuàng)建線程對(duì)象
- 4)啟動(dòng)線程
代碼示例:
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對(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父類
* 重寫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ì)象中,我們可以通過Runable接口來實(shí)現(xiàn)線程程序代碼和數(shù)據(jù)有效的分離。
實(shí)現(xiàn)的步驟:
- 1)創(chuàng)建Runable的實(shí)現(xiàn)類
- 2)重寫run方法
- 3)創(chuàng)建Runable實(shí)例對(duì)象(通過實(shí)現(xiàn)類來實(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單繼承帶來的局限性
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í)行,也獲取不到對(duì)應(yīng)的返回結(jié)果。而且run方法也不能把可能產(chǎn)生的異常拋出。
在JDK1.5之后推出了通過實(shí)現(xiàn)Callable接口的方式來創(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()); // 獲取開啟的線程執(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é)果。通過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中new Date().getTime()指定時(shí)區(qū)的時(shí)間戳問題小結(jié)
本文主要介紹了Java中new Date().getTime()時(shí)間戳問題小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
Spring Data JPA帶條件分頁(yè)查詢實(shí)現(xiàn)原理
這篇文章主要介紹了Spring Data JPA帶條件分頁(yè)查詢實(shí)現(xiàn)原理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
java調(diào)用文心一言API的方法實(shí)現(xiàn)過程
Java是一種廣泛使用的編程語(yǔ)言,用于開發(fā)各種應(yīng)用程序,下面這篇文章主要給大家介紹了關(guān)于java調(diào)用文心一言API的方法實(shí)現(xiàn),文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-12-12
Java getRealPath("/")與getContextPath()區(qū)別詳細(xì)分析
這篇文章主要介紹了Java getRealPath("/")與getContextPath()區(qū)別詳細(xì)分析,本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-08-08

