Java中Thread類基本用法詳解
Thread類的作用
Thread是Java操作多線程最核心的類。
線程創(chuàng)建
Java中創(chuàng)建線程的方法有很多種?。。?/strong>
繼承 Thread, 重寫 run
//繼承Thread類并重寫run方法創(chuàng)建一個(gè)線程
class Thread01 extends Thread{
@Override
public void run() {
System.out.println("hello,thread");
}
}
public class ThreadDemo {
public static void main(String[] args) {
//實(shí)例化一個(gè)線程對(duì)象
Thread01 t=new Thread01();
//真正去申請系統(tǒng)線程,參與CPU調(diào)度
t.start();
}
}實(shí)現(xiàn) Runnable, 重寫 run
//通過繼承Runnable接口并實(shí)現(xiàn)run方法
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("hello,thread");
}
}
public class ThreadDemo {
public static void main(String[] args) {
//實(shí)例化Runnable對(duì)象
MyRunnable runnable=new MyRunnable();
//實(shí)例化線程對(duì)象并綁定任務(wù)
Thread t=new Thread(runnable);
t.start();
}
}繼承 Thread, 重寫 run, 使用匿名內(nèi)部類
//通過Thread匿名內(nèi)部類的方法創(chuàng)建一個(gè)線程
public static void main(String[] args) {
Thread t=new Thread(){
//指定線程任務(wù)
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
};
t.start();
}實(shí)現(xiàn) Runnable, 重寫 run, 使用匿名內(nèi)部類
//通過Runnable匿名內(nèi)部類創(chuàng)建一個(gè)線程
public static void main(String[] args) {
Thread t=new Thread(new Runnable() {
//指定線程的任務(wù)
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
});
t.start();
}使用 lambda 表達(dá)式(最推薦)
//通過Lambda表達(dá)式的方式創(chuàng)建一個(gè)線程
public static void main(String[] args) {
Thread t=new Thread(()->{
System.out.println("Hi");
});
t.start();
}上述方法,只是語法規(guī)則不同,本質(zhì)上是一樣的方式,創(chuàng)造出的線程并無不同。
面試題一:請說明Thread類中run和start的區(qū)別
答案:
作用功能不同:
a.run方法的作用是描述線程具體要執(zhí)行的任務(wù);
b.start方法的作用是真正在操作系統(tǒng)內(nèi)核里創(chuàng)建線程,并讓新線程調(diào)用run方法。
運(yùn)行結(jié)果不同:
a.run方法是一個(gè)類中的普通方法,主動(dòng)調(diào)用和調(diào)用普通方法一樣,會(huì)順序執(zhí)行一次。
b.start調(diào)用方法后,start方法內(nèi)部會(huì)調(diào)用Java本地方法(封裝了對(duì)系統(tǒng)底層的調(diào)用)真正的啟動(dòng)線程,并執(zhí)行run方法中的代碼,run方法執(zhí)行完成后,線程進(jìn)入銷毀階段。
線程中斷
中斷的意思不是指讓線程立即就停止,而是通知線程應(yīng)該要停止,是否真的停止,取決于線程這里具體的代碼寫法。
1.使用標(biāo)志位來控制線程是否要停止
public static boolean flag=true;
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
while (flag){
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(3000);
//在主線程里就可以隨時(shí)通過flag變量的取值,來操作t線程是否結(jié)束
flag=false;
}
- 自定義變量這種方式不能及時(shí)響應(yīng),尤其是在sleep休眠的時(shí)間比較久的時(shí)候。
- 這個(gè)代碼之所以能夠起到修改flag, t線程就結(jié)束,完全取決于 t 線程內(nèi)部的代碼。
- 代碼里通過flag控制循環(huán)。因此這里只是告訴讓這個(gè)線程結(jié)束,這個(gè)線程是否要結(jié)束,啥時(shí)候結(jié)束,都取決于 t 線程內(nèi)部代碼。
2.使用Thread自帶的標(biāo)志位來控制線程是否要停止
public static void main(String[] args) throws InterruptedException {
Thread t=new Thread(()->{
while (!Thread.currentThread().isInterrupted()){
System.out.println("hello Thread");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t.start();
Thread.sleep(3000);
t.interrupt();
}Thread.currentThread():這是Thread類的靜態(tài)方法,通過這個(gè)方法可以獲取到當(dāng)前線程,哪個(gè)線程調(diào)用這個(gè)方法,就得到哪個(gè)線程的對(duì)象引用,類似于this。
isInterrupted():判斷線程是否終止,為true表示被終止,為false表示未被終止。
t.interrupt() :在上述代碼中,主線程調(diào)用t.interrupt(),相當(dāng)于主線程通知 t 線程要終止。

此處interrupt會(huì)做兩件事:
1.把線程內(nèi)部的標(biāo)志位(boolean)給設(shè)置成true。
2.如果線程在進(jìn)行sleep,就會(huì)觸發(fā)異常,把sleep喚醒。
注意:
在喚醒sleep的時(shí)候,會(huì)把剛才設(shè)置的這個(gè)標(biāo)志位,再設(shè)置回false。(清空了標(biāo)志位)
這就導(dǎo)致上述代碼在sleep的異常被catch完了之后,循環(huán)還要繼續(xù)執(zhí)行??!
上述代碼執(zhí)行結(jié)果:
問題一:為啥sleep要清除標(biāo)志位?
喚醒sleep之后,線程到底是否要終止,到底是立即終止還是稍后終止,取決于線程內(nèi)部代碼。
線程等待
線程等待是指一個(gè)線程在執(zhí)行過程中暫停自己的運(yùn)行,并等待其他線程完成一定的操作后再繼續(xù)執(zhí)行。簡單來說,就是控制多個(gè)線程的執(zhí)行順序。
線程等待的實(shí)現(xiàn)方式有很多種,其中最常見的方式是使用線程的join()方法。當(dāng)一個(gè)線程調(diào)用另一個(gè)線程的join()方法時(shí),它會(huì)被阻塞,直到被調(diào)用的線程執(zhí)行完畢并退出。

上述代碼執(zhí)行結(jié)果:

總結(jié)
到此這篇關(guān)于Java中Thread類基本用法的文章就介紹到這了,更多相關(guān)Thread類基本用法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
完美解決idea光標(biāo)變成了insert光標(biāo)狀態(tài)的問題
這篇文章主要介紹了完美解決idea光標(biāo)變成了insert光標(biāo)狀態(tài)的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-02-02
Java實(shí)現(xiàn)多個(gè)wav文件合成一個(gè)的方法示例
這篇文章主要介紹了Java實(shí)現(xiàn)多個(gè)wav文件合成一個(gè)的方法,涉及java文件流讀寫、編碼轉(zhuǎn)換、解析等相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
springboot在filter中如何用threadlocal存放用戶身份信息
這篇文章主要介紹了springboot中在filter中如何用threadlocal存放用戶身份信息,本文章主要描述通過springboot的filter類,在過濾器中設(shè)置jwt信息進(jìn)行身份信息保存的方法,需要的朋友可以參考下2024-07-07
java EasyExcel實(shí)現(xiàn)動(dòng)態(tài)列解析和存表
這篇文章主要為大家介紹了java EasyExcel實(shí)現(xiàn)動(dòng)態(tài)列解析和存表示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-06-06
Java springboot項(xiàng)目jar發(fā)布過程解析
這篇文章主要介紹了Java springboot項(xiàng)目jar發(fā)布過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
Java中為什么要實(shí)現(xiàn)Serializable序列化
在Java編程中,Serializable序列化是一個(gè)常見的概念,它允許對(duì)象在網(wǎng)絡(luò)上傳輸或持久化到磁盤上,本文將深入探討為什么在Java中要實(shí)現(xiàn)Serializable序列化,并通過示例代碼來解釋其重要性2023-10-10
解決SpringBoot2.1.0+RocketMQ版本沖突問題
這篇文章主要介紹了解決SpringBoot2.1.0+RocketMQ版本沖突問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
springboot之Validation參數(shù)校驗(yàn)詳細(xì)解讀
這篇文章主要介紹了springboot之Validation參數(shù)校驗(yàn)詳細(xì)解讀,本篇是關(guān)于springboot的參數(shù)校驗(yàn)知識(shí),當(dāng)然也適用其它java應(yīng)用,讀完本篇將學(xué)會(huì)基本的參數(shù)校驗(yàn),自定義參數(shù)校驗(yàn)和分組參數(shù)校驗(yàn),需要的朋友可以參考下2023-10-10


