欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中Thread類詳解及常用的方法

 更新時(shí)間:2022年05月06日 08:56:45   作者:富春山居_ZYY  
在java中談到線程,必然少不了Thread類,下面這篇文章主要給大家介紹了關(guān)于Java中Thread類及常用的方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下

一、Thread 的常見構(gòu)造方法

方法說(shuō)明
Thread()創(chuàng)建線程對(duì)象
Thread(Runnable target)使用 Runnable 對(duì)象創(chuàng)建線程對(duì)象
Thread(String name)創(chuàng)建線程對(duì)象并命名
Thread(Runnable target,String name)使用 Runnable 對(duì)象創(chuàng)建線程對(duì)象并命名

關(guān)于前兩種方法,在之前的線程創(chuàng)建介紹中有使用到

線程創(chuàng)建根本上來(lái)講有兩種創(chuàng)建方法:

創(chuàng)建一個(gè)繼承自 Thread 類的子類,重寫 Thread 中的 run 方法,調(diào)用 start 方法創(chuàng)建一個(gè)實(shí)現(xiàn) Runnable 接口的類,重寫 Thread 中的 run 方法。創(chuàng)建 Thread 實(shí)例,將自己寫的實(shí)現(xiàn) Runnable 接口的類的實(shí)例設(shè)置進(jìn)去,調(diào)用 start 方法

構(gòu)造方法三和四不過是在前面兩種構(gòu)造方法的基礎(chǔ)上多添加了一個(gè)給線程對(duì)象命名的參數(shù),方便程序員進(jìn)行調(diào)試。

代碼(以構(gòu)造方法四為例):

public class func7 {
    public static void main(String[] args) {
        Thread thread = new Thread(() ->{
            while (true) {
                System.out.println("This is my Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"myThread");
        //此處用 lambda 表達(dá)式代替 Runnable 實(shí)例,更加簡(jiǎn)潔,添加了一個(gè)參數(shù)指定thread線程的名字
        thread.start();
        while (true) {
            System.out.println("my main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

程序員可以通過 JDK 自帶的jconsole工具來(lái)直觀查看這里創(chuàng)建的線程

步驟一:

運(yùn)行程序后,找到自己的 jdk 路徑 -> bin ->jconsole.exe

步驟二:雙擊該 exe 文件。選擇本地進(jìn)程,這里羅列著 Java 進(jìn)程??梢钥匆娢覀兊某绦?func7 ,點(diǎn)擊它。在菜單欄選擇線程一欄

步驟三:查看線程信息

左側(cè)可以選擇需要被查看的線程,可以看見主線程 main和新創(chuàng)建的線程 myThread ,如果沒有重命名操作的話新創(chuàng)建的線程名就會(huì)叫 Thread-0,Thread-1 這樣的名字,不方便查看。

右側(cè)顯示了該線程的被讀取的那一瞬間的狀態(tài),堆棧跟蹤顯示的是代碼具體執(zhí)行的位置

二、Thread 的常見屬性

屬性方法
IDgetId()
名稱getName()
狀態(tài)getState()
優(yōu)先級(jí)getPriority()
是否為后臺(tái)線程isDaemon()
是否存活isAlive()
是否被中斷isInterrupted()

解釋:

  1. 線程的唯一標(biāo)識(shí)就是線程 Id
  2. 名稱在上面的案例中有所體現(xiàn),為調(diào)試提供了便利
  3. 狀態(tài)表示線程當(dāng)前所處的情況,上面的案例中,線程因?yàn)檎{(diào)用了 sleep 方法就進(jìn)入了阻塞狀態(tài)
  4. 優(yōu)先級(jí)表示該線程被調(diào)度到的難易度,高的更容易被調(diào)度到
  5. 判斷是否為后臺(tái)線程。如果是后臺(tái)線程,那么該后臺(tái)線程不會(huì)影響 java 進(jìn)程的結(jié)束;如果是非后臺(tái)線程,JVM 就會(huì)等到所有的非后臺(tái)線程執(zhí)行完畢,才會(huì)結(jié)束運(yùn)行,因此會(huì)影響到總進(jìn)程的結(jié)束
  6. 是否存活是來(lái)判斷線程是否還存在的方法。當(dāng)創(chuàng)建出 Thread 實(shí)例對(duì)象時(shí),線程未必就創(chuàng)建了,需要調(diào)用 start 方法,才是真正的創(chuàng)建了線程。當(dāng)線程中的 run 方法執(zhí)行完畢,線程結(jié)束被銷毀了,創(chuàng)建出的實(shí)例對(duì)象還沒被銷毀回收。所以說(shuō),創(chuàng)建出的實(shí)例對(duì)象和線程的生命周期是不完全相同的

在線程的狀態(tài)中,除了NEW 和 TERMINATED 以外的狀態(tài)都是活著的

代碼:

public class func8 {
    public static void main(String[] args) {
        Thread t = new Thread(()->{
            for (int i = 0;i < 5;i ++) {
                System.out.println("新線程~");
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"newThread");
        System.out.println("新線程狀態(tài):" +t.getState());
        //創(chuàng)建了對(duì)象,沒創(chuàng)建線程
        t.start();
        System.out.println("新線程狀態(tài):" +t.getState());
        //創(chuàng)建了線程
        System.out.println("新線程Id:"+t.getId());
        System.out.println("新線程名稱:"+t.getName());
        System.out.println("新線程是否為后臺(tái)線程:" + t.isDaemon());
        System.out.println("新線程是否被中斷:" + t.isInterrupted());
        System.out.println("新線程優(yōu)先級(jí):" + t.getPriority());
        System.out.println("主線程名稱:"+Thread.currentThread().getName());
        while (t.isAlive()) {} //當(dāng)t線程還存在時(shí),主線程就擱這兒循環(huán)著,直到線程結(jié)束
        System.out.println("新線程狀態(tài):" +t.getState());//線程結(jié)束
    }
}

結(jié)果:

三、創(chuàng)建線程

創(chuàng)建 Thread 類的對(duì)象不意味著線程被創(chuàng)建出,start() 方法才是真正的在操作系統(tǒng)內(nèi)部創(chuàng)建一個(gè)新的線程,通過重寫 run 方法來(lái)描述需要執(zhí)行的任務(wù),從而真正實(shí)現(xiàn)了多線程運(yùn)行。

四、中斷線程

方法一:手動(dòng)設(shè)置標(biāo)志位,作為中斷線程的條件

public class func9 {
    private static Boolean flag = false;//手動(dòng)設(shè)置的標(biāo)志位 flag
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while (!flag) {
                //flag 為真時(shí)停止循環(huán)
                System.out.println("myThread");
                try {
                    Thread.sleep(1000);//打印一次,阻塞一秒
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        t.start();//創(chuàng)建了線程 t
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        //等3秒后,在主線程中將 flag 的值改成 true,從而使線程t循環(huán)條件不成立
    }
}

方法二:使用 Thread 實(shí)例中的標(biāo)志位

public class func10 {
    public static void main(String[] args) {
        Thread t = new Thread() {
            @Override
            public void run() {
                //通過 isInerrupted()判斷標(biāo)志位是否為true,為true說(shuō)明線程要退出
                while (!this.isInterrupted()) {
                   System.out.println("my Thread");
                   try {
                       Thread.sleep(1000);
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                       //System.out.println("完善工作");
                       //break;
                   }
               }
            }
        };
        t.start();//創(chuàng)建新的線程
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
        //t線程運(yùn)行3秒后,通過 interrupt() 方法將標(biāo)志位設(shè)置為 true
    }
}

結(jié)果:

可以看見當(dāng)3秒后標(biāo)志位設(shè)置為 true,希望 t 線程中斷退出時(shí),結(jié)果只是報(bào)了個(gè) InterruptedException 異常。

事實(shí)上,當(dāng)調(diào)用 interrupt 方法時(shí),如果線程為就緒狀態(tài),就會(huì)直接修改線程中的標(biāo)志位;如果是阻塞狀態(tài),就會(huì)引起 InterruptedException 異常(因?yàn)檎{(diào)用了 sleep 方法,正阻塞著呢,結(jié)果被強(qiáng)行呼醒了)

但收到中斷線程這個(gè)信號(hào)后,出現(xiàn)了異常,只是單純的打印了一下異常,并沒有對(duì)出現(xiàn)的異常進(jìn)行反應(yīng),于是 t 線程就繼續(xù)循環(huán),就好像中斷線程這個(gè)信號(hào)只是提醒了一下,線程打個(gè)日志就完事,當(dāng)做沒聽見。

事實(shí)上,這樣的機(jī)制是有存在的道理的,如果調(diào)用了 interrupt 方法后,線程說(shuō)中斷就中斷,是非常不符合常理的,此時(shí)并不知道線程執(zhí)行到什么地方,收到中斷的信號(hào)后,怎么說(shuō)也要進(jìn)行收尾工作,由線程自己決定什么時(shí)候被銷毀

因此我們要在捕捉到 InterruptedException 異常后,進(jìn)行工作完善,然后通過 break 跳出循環(huán),結(jié)束線程

方法二和方法一相比更加好。因?yàn)榉椒ㄒ恢械闹袛鄻?biāo)志被修改后,即使當(dāng)時(shí)正在 sleep ,也會(huì)把當(dāng)下的 sleep 的時(shí)間過完,才會(huì)進(jìn)行下一輪判斷,才知道線程被中斷。方法二即使是在 sleep,收到中斷信號(hào)后,就會(huì)馬上被喚醒,中斷信息收到的更加的及時(shí)。

結(jié)果:

五、線程等待

通過 join() 方法來(lái)決定線程執(zhí)行順序(主要控制結(jié)束線程的順序)。

public class func11 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
           for (int i = 0;i < 3;i ++) {
               System.out.println("my Thread~~");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        t1.start();
        //t1.join();
        for (int i = 0;i < 3;i ++) {
            System.out.println("my main!!");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

結(jié)果:

在沒有調(diào)用 join 方法時(shí),main 線程和 t1 線程是并發(fā)的,結(jié)果輸出是相間的。調(diào)用 join 方法后,main 線程就會(huì)阻塞等待,要等 t1 線程執(zhí)行完畢,才會(huì)執(zhí)行 join 方法后的內(nèi)容

不帶參數(shù)的 join 方法,等待結(jié)束的條件就是 t1 線程結(jié)束,沒結(jié)束就會(huì)一直死等;該方法也可以帶參數(shù),通過參數(shù)來(lái)指定等待時(shí)間

六、獲取線程引用

在線程代碼中,需要獲取當(dāng)前線程對(duì)應(yīng)的 Thread 類的實(shí)例化對(duì)象,才能進(jìn)行更多的操作

方法一:通過繼承 Thread 類創(chuàng)建的線程,可以在重寫的 run 方法中通過 this 獲取當(dāng)前線程的實(shí)例

在上面的中斷線程中的方法二中就是通過 this.isInterrupted() 來(lái)獲取當(dāng)前實(shí)例是否被中斷的信息。

如果將創(chuàng)建線程的方式改成創(chuàng)建 Runnable 實(shí)例的方法,當(dāng)前的run 方法就不是 Thread 類的方法,this 指向的是 Runnable,就沒有辦法獲取 Thread 實(shí)例,更沒有辦法使用其中的方法

方法二:通過 Thread 類的 currentThread() 方法,哪個(gè)線程調(diào)用了該方法,就返回哪個(gè)線程的實(shí)例對(duì)象

七、線程休眠

該方法在前面經(jīng)常介紹,那就是 sleep 方法

一旦調(diào)用 sleep 方法,線程就會(huì)阻塞等待,等待的時(shí)間取決于指定的參數(shù)

操作系統(tǒng)是以線程為單位進(jìn)行調(diào)度的,每個(gè)線程都對(duì)應(yīng)著一個(gè) PCB,并通過雙向鏈表組織這些 PCB

操作系統(tǒng)調(diào)度 PCB 時(shí),就是從就緒隊(duì)列中選出一個(gè) PCB 去 CPU 上執(zhí)行,當(dāng)執(zhí)行著的線程調(diào)用了 sleep 方法,這個(gè) PCB 就會(huì)被移動(dòng)到阻塞隊(duì)列中,等到 sleep 的時(shí)間到了,就會(huì)回到就緒隊(duì)列中,準(zhǔn)備好被執(zhí)行

join 方法也會(huì)產(chǎn)生阻塞等待,就像線程等待中的例子,main 線程執(zhí)行到 join方法后,就到阻塞隊(duì)列中,等待對(duì)應(yīng)的 t1 線程執(zhí)行完畢,才會(huì)回到就緒隊(duì)列中,做好被執(zhí)行的準(zhǔn)備

八、線程狀態(tài)

從之前的 Thread 的常見屬性這里的代碼案例可以看出來(lái)線程的狀態(tài)不只是就緒和阻塞,即使是阻塞也分成好幾種阻塞類型

//線程的狀態(tài)是一個(gè)枚舉類型 Thread.State
//打印 Java 線程中的所有狀態(tài)
public class func13 {
    public static void main(String[] args) {
        for (Thread.State state : Thread.State.values()) {
            System.out.println(state);
        }
    }
}

結(jié)果:

  • NEW:表示 Thread 類的對(duì)象創(chuàng)建出,但是線程還沒有被創(chuàng)建,即沒有調(diào)用 start 方法
  • RUNNABLE:就緒狀態(tài)
  • BLOCKED:等待鎖時(shí)的狀態(tài)(期待下一篇關(guān)于線程安全的博客)
  • WAITING:通過 wait 方法觸發(fā)(期待之后的博客)
  • TIMED_WAITING:通過 sleep 方法產(chǎn)生
  • TERMINATED:線程已經(jīng)執(zhí)行完畢,但 Thread 類的對(duì)象還存在,未被銷毀

總結(jié)

到此這篇關(guān)于Java中Thread類詳解及常用的方法的文章就介紹到這了,更多相關(guān)Java Thread類方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解常用的Spring Bean擴(kuò)展接口

    詳解常用的Spring Bean擴(kuò)展接口

    本篇文章主要介紹了一些常用的Spring Bean擴(kuò)展接口以及它們的簡(jiǎn)單用法,具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧
    2017-05-05
  • Spring JPA整合QueryDSL的示例代碼

    Spring JPA整合QueryDSL的示例代碼

    這篇文章主要介紹了Spring JPA整合QueryDSL的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • 自定義類加載器的父類為何是AppClassLoader說(shuō)明

    自定義類加載器的父類為何是AppClassLoader說(shuō)明

    這篇文章主要介紹了自定義類加載器的父類為何是AppClassLoader說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-11-11
  • 使用logback屏蔽一些包的日志

    使用logback屏蔽一些包的日志

    這篇文章主要介紹了使用logback屏蔽一些包的日志,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧
    2020-12-12
  • JDK1.8中的ConcurrentHashMap使用及場(chǎng)景分析

    JDK1.8中的ConcurrentHashMap使用及場(chǎng)景分析

    這篇文章主要介紹了JDK1.8中的ConcurrentHashMap使用及場(chǎng)景分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-01-01
  • SpringMVC中@RequestMapping注解的實(shí)現(xiàn)

    SpringMVC中@RequestMapping注解的實(shí)現(xiàn)

    RequestMapping是一個(gè)用來(lái)處理請(qǐng)求地址映射的注解,本文主要介紹了SpringMVC中@RequestMapping注解的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-01-01
  • Spring?Boot?Aop執(zhí)行順序深入探究

    Spring?Boot?Aop執(zhí)行順序深入探究

    這篇文章主要為大家介紹了Spring?Boot?Aop執(zhí)行順序深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • jdk動(dòng)態(tài)代理使用實(shí)例詳解

    jdk動(dòng)態(tài)代理使用實(shí)例詳解

    JDK動(dòng)態(tài)代理是代理模式的一種實(shí)現(xiàn)方式,因?yàn)樗腔诮涌趤?lái)做代理的,所以也常被稱為接口代理,下面這篇文章主要給大家介紹了關(guān)于jdk動(dòng)態(tài)代理使用的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-06-06
  • java自定義JDBC實(shí)現(xiàn)連接池

    java自定義JDBC實(shí)現(xiàn)連接池

    本文主要介紹了java自定義JDBC實(shí)現(xiàn)連接池,包含實(shí)現(xiàn)JDBC連接池以及SQLException?異常的處理,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • SpringBoot中使用@ControllerAdvice注解詳解

    SpringBoot中使用@ControllerAdvice注解詳解

    這篇文章主要介紹了SpringBoot中使用@ControllerAdvice注解詳解,@ControllerAdvice,是Spring3.2提供的新注解,它是一個(gè)Controller增強(qiáng)器,可對(duì)controller中被 @RequestMapping注解的方法加一些邏輯處理,需要的朋友可以參考下
    2023-10-10

最新評(píng)論