最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java線程的屬性深入理解

 更新時(shí)間:2025年11月07日 10:57:27   作者:摸魚(yú)的老譚  
本文介紹了Java線程的幾個(gè)核心屬性,包括線程ID、線程名稱(chēng)、線程狀態(tài)、優(yōu)先級(jí)、守護(hù)線程、是否存活以及異常處理器,通過(guò)這些屬性的操作,可以更好地理解和控制線程的行為,感興趣的朋友跟隨小編一起看看吧

上一節(jié)創(chuàng)建了線程后,本小節(jié)著重關(guān)注線程的屬性,在Thread類(lèi)中提供各種方法用于獲取或設(shè)置相關(guān)屬性,我們通過(guò)這些屬性的操作加深對(duì)線程的理解。

20.1 線程ID

線程類(lèi)中有一個(gè)屬性 tid,它是一個(gè)正的長(zhǎng)整型數(shù)字,在創(chuàng)建此線程時(shí)生成,用于標(biāo)識(shí)此線程實(shí)例。線程實(shí)例的該屬性是唯一的,并在其生命周期內(nèi)保持不變。

使用方法 threadId( ) 獲取線程屬性tid,使用方式如下:

Thread thread = new Thread();
System.out.println(thread.threadId());    // 輸出 36

另外還有一個(gè)在Java 19標(biāo)識(shí)為過(guò)時(shí)的方法getId()與threadId()效果一樣,實(shí)際上內(nèi)部就是直接調(diào)用threadId()方法。

20.2 線程的名稱(chēng)

Thread類(lèi)中的屬性name用于表示線程的名稱(chēng),默認(rèn)產(chǎn)生規(guī)則如下:

this.name = (name != null) ? name : genThreadName();

genThreadName方法體如下:

return "Thread-" + ThreadNumbering.next();

后面的靜態(tài)方法next()產(chǎn)生從0遞增的整數(shù),內(nèi)部使用線程安全的方式實(shí)現(xiàn)。

例如下面的例子:

Thread thread0 = new Thread();
System.out.println(thread0.getName());
Thread thread1 = new Thread();
System.out.println(thread1.getName());
Thread thread2 = new Thread(() -> {
    Thread thread3 = new Thread();
    System.out.println(thread3.getName());
});
System.out.println(thread2.getName());
thread2.start();

運(yùn)行之后,輸出的線程名是:

Thread-0
Thread-1
Thread-2
Thread-3

如果我們顯式設(shè)置線程的name屬性,則可以調(diào)用setName為線程賦一個(gè)自定義名稱(chēng):

Thread thread0 = new Thread();
thread0.setName("這是Thread0");
System.out.println(thread0.getName());  
Thread thread1 = new Thread();
System.out.println(thread1.getName());

運(yùn)行之后,輸出的線程名如下,可以看出來(lái),其他的線程默認(rèn)名稱(chēng)沒(méi)有影響:

這是Thread0
Thread-1

20.3 線程的狀態(tài)

線程從創(chuàng)建到結(jié)束運(yùn)行,中間會(huì)有若干狀態(tài),在內(nèi)部使用FieldHolder類(lèi)型屬性holder封裝了一個(gè) threadStatus 屬性表示線程的狀態(tài),它是一個(gè)int類(lèi)型,不過(guò)只能獲取并不能直接設(shè)置狀態(tài)屬性。

線程的狀態(tài)有以下幾種,但同一時(shí)刻只有一種狀態(tài):

  • 新創(chuàng)建(New):使用new創(chuàng)建一個(gè)線程時(shí),代表線程的對(duì)象已經(jīng)被初始化,但尚未調(diào)用start方法
  • 可運(yùn)行(Runnable):一旦調(diào)用了start方法,就是可運(yùn)行的,但這只說(shuō)明線程目前處于的狀態(tài)
  • 被阻塞(Blocked):線程是可以執(zhí)行的,但由于某些因素的阻礙處于停滯狀態(tài),一般是正在等待一個(gè)鎖,以訪問(wèn)某個(gè)對(duì)象
  • 等待(Waiting):無(wú)限期的等待另一個(gè)線程來(lái)執(zhí)行某一個(gè)動(dòng)作
  • 計(jì)時(shí)等待(Timed waiting):在指定限期內(nèi)等待另一個(gè)線程來(lái)執(zhí)行某一個(gè)動(dòng)作
  • 被終止(Terminatewd):線程的正式結(jié)束方式,run方法執(zhí)行完畢并返回

這幾種狀態(tài)之間可以互相轉(zhuǎn)換,可以使用Thread的getState()方法獲取其當(dāng)前狀態(tài):

State getState()

返回的結(jié)果是State枚舉類(lèi)型,其實(shí)例如下:

public enum State {
    NEW,
    RUNNABLE,
    BLOCKED,
    WAITING,
    TIMED_WAITING,
    TERMINATED;
}

需要注意的是在調(diào)用 getState() 方法之后,線程的狀態(tài)可能會(huì)發(fā)生變化。因此,通過(guò)調(diào)用 getState() 所獲得的狀態(tài)可能無(wú)法反映線程在此刻的實(shí)際狀態(tài)。例如下面的代碼中,狀態(tài)會(huì)隨著代碼的執(zhí)行有變化:

Thread thread = new Thread(() -> {
    System.out.println(Thread.currentThread().getState());   // RUNNABLE
});
System.out.println(thread.getState());                       // NEW
thread.start();
System.out.println(thread.getState());                       // RUNNABLE
Thread.sleep(1000);
System.out.println(thread.getState());                       // TERMINATED

20.4 線程的優(yōu)先級(jí)

Thread 類(lèi)中的優(yōu)先級(jí)也是被內(nèi)部屬性 holder 封裝的一個(gè) int 屬性 priority,不過(guò)Thread類(lèi)提供的對(duì)于優(yōu)先級(jí)的get與set方法。

線程優(yōu)先級(jí)由線程調(diào)度器用于決定每個(gè)線程何時(shí)能夠運(yùn)行。理論上,在給定的一段時(shí)間內(nèi),優(yōu)先級(jí)較高的線程會(huì)比優(yōu)先級(jí)較低的線程獲得更多的 CPU 時(shí)間。但在實(shí)際操作中,一個(gè)線程所獲得的 CPU 時(shí)間通常取決于除其優(yōu)先級(jí)之外的多個(gè)因素。(例如,操作系統(tǒng)實(shí)現(xiàn)多任務(wù)處理的方式會(huì)影響 CPU 時(shí)間的相對(duì)可用性。)優(yōu)先級(jí)較高的線程也可以搶占優(yōu)先級(jí)較低的線程。例如,當(dāng)一個(gè)優(yōu)先級(jí)較低的線程正在運(yùn)行,而一個(gè)優(yōu)先級(jí)較高的線程恢復(fù)運(yùn)行(例如從睡眠或等待 I/O 事件中恢復(fù))時(shí),它將搶占優(yōu)先級(jí)較低的線程。

理論上,具有相同優(yōu)先級(jí)的線程應(yīng)當(dāng)能夠平等地使用 CPU 資源。不過(guò)要注意,Java 是為多種環(huán)境設(shè)計(jì)的,其中一些環(huán)境對(duì)多任務(wù)處理的實(shí)現(xiàn)方式與其他環(huán)境截然不同。為了安全起見(jiàn),具有相同優(yōu)先級(jí)的線程應(yīng)當(dāng)偶爾讓出控制權(quán)。這能確保在非搶占式操作系統(tǒng)中,所有線程都有機(jī)會(huì)運(yùn)行。實(shí)際上,即使在非搶占式環(huán)境中,大多數(shù)線程仍有機(jī)會(huì)運(yùn)行,因?yàn)榇蠖鄶?shù)線程不可避免地會(huì)遇到一些阻塞情況,比如等待輸入/輸出操作。當(dāng)這種情況發(fā)生時(shí),被阻塞的線程會(huì)被暫停,其他線程可以運(yùn)行。但是,如果我們希望實(shí)現(xiàn)流暢的多線程執(zhí)行,最好不要依賴(lài)這一點(diǎn)。此外,某些類(lèi)型的任務(wù)是 CPU 密集型的。這類(lèi)線程會(huì)占據(jù) CPU 的大部分時(shí)間。對(duì)于這些類(lèi)型的線程,應(yīng)該偶爾讓出控制權(quán),以便其他線程能夠運(yùn)行。

線程優(yōu)先級(jí)用數(shù)字來(lái)表示,范圍從1到10;主線程的缺省優(yōu)先級(jí)是5,子線程的優(yōu)先級(jí)默認(rèn)與其父線程相同。

在Thread類(lèi)中聲明了三個(gè)與優(yōu)先級(jí)相關(guān)的常量:

public static final int MIN_PRIORITY = 1;    // 最低優(yōu)先級(jí)
public static final int NORM_PRIORITY = 5;   // 線程的默認(rèn)優(yōu)先級(jí)
public static final int MAX_PRIORITY = 10;   // 最高優(yōu)先級(jí)

獲取與設(shè)置優(yōu)先級(jí)的方法:

  • final int getPriority():獲取線程的優(yōu)先級(jí)
  • final void setPriority(int newPriority):設(shè)置線程的優(yōu)先級(jí),參數(shù)newPriority應(yīng)在1-10之間

下面的示例演示了優(yōu)先級(jí)設(shè)置與獲取方法的使用:

Thread thread = new Thread(() -> {
});
System.out.println(thread.getPriority());     // 輸出 5 
thread.setPriority(7);                        // 設(shè)置優(yōu)先級(jí)為 7
System.out.println(thread.getPriority());     // 輸出 7

20.5 守護(hù)線程

Thread類(lèi)的屬性holder中封裝了屬性daemon表示該線程是否是守護(hù)線程。

守護(hù)(Daemon)線程是一種服務(wù)提供者線程,而非守護(hù)線程(或用戶(hù)線程)則是使用守護(hù)線程所提供服務(wù)的線程。服務(wù)提供者在沒(méi)有服務(wù)消費(fèi)者時(shí)不應(yīng)存在。JVM 會(huì)遵循這一邏輯,當(dāng) JVM 發(fā)現(xiàn)應(yīng)用程序中的所有線程均為守護(hù)線程時(shí),它會(huì)退出該應(yīng)用程序。請(qǐng)注意,如果應(yīng)用程序中只有守護(hù)線程,JVM 在退出應(yīng)用程序前不會(huì)等待這些守護(hù)線程完成。

可以通過(guò)使用 setDaemon() 方法并傳入 true 參數(shù)來(lái)將一個(gè)線程設(shè)為守護(hù)線程。在啟動(dòng)線程之前必須先調(diào)用線程的setDaemon() 方法。否則,會(huì)拋出 IllegalThreadStateException 異常??梢允褂?isDaemon() 方法來(lái)檢查一個(gè)線程是否為守護(hù)線程。

當(dāng)創(chuàng)建一個(gè)線程時(shí),該線程的 daemon 屬性與創(chuàng)建該線程的線程的 daemon 屬性相同。換句話(huà)說(shuō),新線程會(huì)繼承其創(chuàng)建線程的 daemon 屬性。

Thread thread = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("你好");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
});
thread.setDaemon(true);
thread.start();
System.out.println("主線程");

運(yùn)行之后結(jié)果是:

主線程
你好

當(dāng)主線程結(jié)束后,因?yàn)橹挥惺刈o(hù)線程,應(yīng)用程序會(huì)退出。

但是如果不是守護(hù)線程,如下:

Thread thread = new Thread(() -> {
    for (int i = 0; i < 5; i++) {
        System.out.println("你好");
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
});
thread.start();
System.out.println("主線程");

運(yùn)行結(jié)果如下:

主線程
你好
你好
你好
你好
你好

可以看到,線程執(zhí)行完成后應(yīng)用程序會(huì)退出。

判斷一個(gè)線程是否守護(hù)線程,可以使用以下方法:

public final boolean isDaemon(){}

該方法用于測(cè)試線程是否為守護(hù)線程。要注意的是虛擬線程的守護(hù)狀態(tài)始終為 true。

20.6 是否存活

內(nèi)部屬性eetop僅供 JVM 專(zhuān)用,保存底層 VM JavaThread 的地址,在線程啟動(dòng)時(shí)設(shè)置為非零值,在線程終止時(shí)重置為零。非零值表示此線程處于存活狀態(tài),使用方法 isAlive( ) 判斷線程是否處于存活狀態(tài)。

Thread thread = new Thread(() -> {
});
thread.start();
System.out.println(thread.isAlive());    // true
Thread.sleep(500);                       // 休眠500毫秒,異常已處理
System.out.println(thread.isAlive());    // false

20.7 設(shè)置異常處理器

當(dāng)線程中向外拋出了未捕獲異常時(shí),可以為線程實(shí)例設(shè)置一個(gè)異常處理對(duì)象到uncaughtExceptionHandler屬性,該實(shí)例的類(lèi)型是 Thread.UncaughtExceptionHandler 的實(shí)現(xiàn),如:

public class MyThreadExceptionHandler implements Thread.UncaughtExceptionHandler {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
        System.out.println(t.getName()+":"+e.getMessage());
    }
}

上面重寫(xiě)的方法 uncaughtException() 接收兩個(gè)參數(shù),第一個(gè)參數(shù)t是拋出異常的線程,第二個(gè)參數(shù)是拋出異常對(duì)象。

下面的代碼中,創(chuàng)建了新的線程,在其中拋出了異常,不過(guò)隨后使用 setUncaughtExceptionHandler 方法設(shè)置了異常處理類(lèi)的實(shí)例,則線程任務(wù)運(yùn)行時(shí)的未捕獲異常會(huì)被 uncaughtException() 方法捕獲到:

Thread thread = new Thread(() -> {
    throw new RuntimeException(Thread.currentThread().getName() + "中的異常");
});
MyThreadExceptionHandler exceptionHandler = new MyThreadExceptionHandler();
thread.setUncaughtExceptionHandler(exceptionHandler);
thread.start();

運(yùn)行之后的結(jié)果為:

Thread-0:Thread-0中的異常

除了上面的 setUncaughtExceptionHandler 方法之外,Thread類(lèi)還提供了一個(gè)靜態(tài)方法用于為所有線程設(shè)置異常處理邏輯,不過(guò)它的處理邏輯會(huì)被非靜態(tài)的 setUncaughtExceptionHandler 覆蓋:

MyThreadExceptionHandler exceptionHandler = new MyThreadExceptionHandler();
Thread.setDefaultUncaughtExceptionHandler(exceptionHandler);

對(duì)于異常處理的流程如下:

  • 如果線程使用 setUncaughtExceptionHandler() 方法設(shè)置了異常處理器,則會(huì)調(diào)用該處理器的 uncaughtException() 方法。
  • 如果一個(gè)線程沒(méi)有設(shè)置異常處理器,那么將調(diào)用其線程組的 uncaughtException() 方法,如果該線程組有父線程組,則調(diào)用其父線程組的 uncaughtException() 方法。否則,檢查是否設(shè)置了默認(rèn)的異常處理器。如果找到了默認(rèn)的未異常處理器,則調(diào)用其 uncaughtException() 方法。如果沒(méi)有找到默認(rèn)的異常處理器,則在標(biāo)準(zhǔn)錯(cuò)誤流上打印一條消息。如果既未找到默認(rèn)的異常處理器,又拋出了 ThreadDeath 異常,則不執(zhí)行任何操作。

20.8 小結(jié)

本節(jié)詳細(xì)介紹了線程的幾個(gè)核心屬性,主要有:1)線程ID(tid)是唯一標(biāo)識(shí)符,通過(guò)threadId()獲??;2)線程名稱(chēng)(name)默認(rèn)為"Thread-數(shù)字",可通過(guò)setName()修改;3)線程狀態(tài)(threadStatus)包括NEW、RUNNABLE等6種,使用getState()獲??;4)優(yōu)先級(jí)(priority)范圍1-10,通過(guò)get/setPriority()方法操作;5)守護(hù)線程(daemon)屬性決定線程是否隨主線程結(jié)束,通過(guò)is/setDaemon()方法管理。

到此這篇關(guān)于Java學(xué)習(xí)之旅第三季-20:線程的屬性的文章就介紹到這了,更多相關(guān)Java線程的屬性?xún)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringAop切入點(diǎn)execution表達(dá)式的深入講解

    SpringAop切入點(diǎn)execution表達(dá)式的深入講解

    Spring AOP 可能會(huì)經(jīng)常使用 execution切入點(diǎn)指示符,下面這篇文章主要給大家介紹了關(guān)于SpringAop切入點(diǎn)execution表達(dá)式的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • spring security中Authority、Role的區(qū)別及說(shuō)明

    spring security中Authority、Role的區(qū)別及說(shuō)明

    這篇文章主要介紹了spring security中Authority、Role的區(qū)別及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Spring在代碼中獲取bean的方法小結(jié)

    Spring在代碼中獲取bean的方法小結(jié)

    在工作中有時(shí)候我們需要在非spring依賴(lài)注入或管理的類(lèi)中獲取service、dao等bean對(duì)象,這時(shí)候用@Autowired和@Resource顯然是不行的,那么下面這篇文章就給大家了整理幾種獲取bean的方式,對(duì)大家的學(xué)習(xí)和工作具有一定的參考借鑒,下面來(lái)一起看看吧。
    2016-11-11
  • Spring中Xml屬性配置的解析全過(guò)程記錄

    Spring中Xml屬性配置的解析全過(guò)程記錄

    這篇文章主要給大家介紹了關(guān)于Spring中Xml屬性配置的解析全過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Java兩個(gè)List<T> 求交集,差集,并集,去重后的并集

    Java兩個(gè)List<T> 求交集,差集,并集,去重后的并集

    本文主要介紹了Java兩個(gè)List<T> 求交集,差集,并集,去重后的并集,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • 帶你深入概括Java!六、方法和方法重載!(推薦)

    帶你深入概括Java!六、方法和方法重載?。ㄍ扑])

    這篇文章主要介紹了Java方法和方法重載,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • Java 泛型全解析

    Java 泛型全解析

    這篇文章主要介紹了Java 泛型的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下
    2020-08-08
  • Flink實(shí)戰(zhàn)之實(shí)現(xiàn)流式數(shù)據(jù)去重

    Flink實(shí)戰(zhàn)之實(shí)現(xiàn)流式數(shù)據(jù)去重

    流式數(shù)據(jù)是一種源源不斷產(chǎn)生的數(shù)據(jù),本文探索了一種流式大數(shù)據(jù)的實(shí)時(shí)去重方法,不一定適用于所有場(chǎng)景,不過(guò)或許可以給面對(duì)相似問(wèn)題的你一點(diǎn)點(diǎn)啟發(fā),
    2025-03-03
  • 詳解Spring Data JPA使用@Query注解(Using @Query)

    詳解Spring Data JPA使用@Query注解(Using @Query)

    本篇文章主要介紹了詳解Spring Data JPA使用@Query注解(Using @Query),具有一定的參考價(jià)值,有興趣的可以了解一下
    2017-07-07
  • SpringBoot配置diff的實(shí)戰(zhàn)指南

    SpringBoot配置diff的實(shí)戰(zhàn)指南

    做配置管理時(shí),diff 是繞不開(kāi)的功能,比如運(yùn)維要修改生產(chǎn)環(huán)境配置,改之前總想確認(rèn)一下具體動(dòng)了什么,通常我們會(huì)想到用 Unix 的 diff 命令或者 Git 的 diff 功能,所以本文給大家介紹了SpringBoot配置diff的實(shí)戰(zhàn)指南,需要的朋友可以參考下
    2026-01-01

最新評(píng)論

阿瓦提县| 七台河市| 江陵县| 长宁区| 宾川县| 杭锦后旗| 全椒县| 陕西省| 桦南县| 百色市| 锡林郭勒盟| 体育| 获嘉县| 香格里拉县| 建阳市| 郑州市| 水富县| 平果县| 二连浩特市| 鄂伦春自治旗| 肥城市| 平南县| 阳曲县| 赤水市| 桃源县| 诏安县| 南宫市| 灵武市| 宜君县| 建昌县| 云南省| 屏山县| 永吉县| 揭西县| 禹城市| 海城市| 广元市| 徐汇区| 双峰县| 高淳县| 新源县|