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

Java中Thread類的使用和它的屬性

 更新時間:2022年04月12日 15:38:17   作者:小小怪下士~  
在java中可以進行多線程編程,在java標準庫中提供了一個Thread類,來表示線程操作,本文主要介紹了Java中Thread類的使用和它的屬性,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

在java中可以進行多線程編程,在java標準庫中提供了一個Thread類,來表示線程操作。Thread類可以視為java標準庫提供的一組解決多線程編程的一組API.

創(chuàng)建好的Thread實例,和操作系統(tǒng)中的線程是一一對應(yīng)的。操作系統(tǒng)提供了關(guān)于線程的API(C語言風(fēng)格),java在對其進行封裝就成Thread類。

創(chuàng)建線程

方法一:繼承Thread類

class MyThread extends Thread{
    @Override
    public void run() {
        //此時只是定義處理一個線程類,在系統(tǒng)中總是還沒有創(chuàng)建出 新的線程。
        System.out.println("hello thread");
    }
}
public class TestDemo11 {
    public static void main(String[] args) {
        //創(chuàng)建線程
        Thread t = new MyThread();
        //啟動線程,在系統(tǒng)中創(chuàng)建出了新的線程
        t.start();
    }
}

在這里插入圖片描述

線程之間是并發(fā)執(zhí)行的

class MyThread3 extends Thread{
    @Override
    public void run() { //定義一個線程類
        while (true) {
            System.out.println("hello thread");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
public class TestDemo13 {
    public static void main(String[] args) {
        Thread t = new MyThread3();
        t.start();//啟動t線程
        while(true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在這里插入圖片描述

在這里插入圖片描述

我們可以看到1s當(dāng)執(zhí)行一個線程中的代碼之后 進入阻塞狀態(tài),那么下一秒要喚醒那個線程呢?

我們可以看到執(zhí)行出來的兩個線程中打印出來的日志的順序是不確定的。每一輪,1s之后,到底是喚醒thread線程還是喚醒main線程,這是不確定的。(搶占式執(zhí)行),對于操作系統(tǒng)來說,從宏觀上對線程進行調(diào)度的順序是隨機的

此處在說明一下Thread.sleep()方法,sleep()這個方法到了ms級別沒有那么精確。當(dāng)調(diào)用這個方法之后,把線程強制處于中阻塞(睡眠狀態(tài)),但是當(dāng)阻塞時間結(jié)束之后,并不是立即在cup上繼續(xù)執(zhí)行該線程,如果Thread.sleep(1000),當(dāng)通過1s后,阻塞時間結(jié)束,但是在1001ms,線程也許不會立即執(zhí)行。也許操作系統(tǒng)中的cup在忙別的線程?;蛟S該線程在1006ms才執(zhí)行。

方法二:實現(xiàn)Runnable接口中的run()方法

//Runnable其實就是描述一個任務(wù)
//創(chuàng)建一個類,實現(xiàn)Runnable接口,重寫Runnable類中的run方法,在run()方法中,描述的是該線程要指向的哪些任務(wù)。
class MyThread2 implements Runnable{
    @Override
    public void run() {
        System.out.println("hello thread");
    }
}
public class TestDemo12 {
    public static void main(String[] args) {
        //創(chuàng)建線程,把創(chuàng)建好的Runnable實例傳給Thread實例
        Thread t = new Thread(new MyThread2());
        t.start();
    }
}

方法三:利用內(nèi)部類

方法三其實是方法一個的翻版,就是把上面的兩種代碼,改成了匿名內(nèi)部類。

public class TestDemo14 {
    public static void main(String[] args) {
        Thread t1 = new MyThread(){
            @Override
            public void run() {
                System.out.println("hello thread1");
            }
        };
        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello thread2");
            }
        });
        t1.start();
        t2.start();
    }
}

在這里插入圖片描述

方法四:使用lambmd表達式

public class TestDemo15 {
    public static void main(String[] args) {
        //其實就是使用lambad表達式代替Runnable
        Thread t1 = new Thread(()->{
            //()表示無參的run()方法
            System.out.println("hello thread1");
        });

    }
}

使用線程的好處

為了更方便的體現(xiàn)出多線程的好處,在這里我們從0開始自增1,一直自增到10_0000_0000,使用串行方法,和并行方法,并且獲取他們執(zhí)行代碼的時間,進行比較。

public class TestDemo16 {
    public static void func1() throws InterruptedException {
        long big = System.currentTimeMillis();
        //串行執(zhí)行
        Thread t = new Thread(()->{
            long a = 0;
           for(long i = 0;i<10_0000_0000;i++){
               a++;
           }
        });
        t.start();
        t.join();
        long end = System.currentTimeMillis();
        System.out.println("串行消耗時間:" + (end - big) + "ms");
    }
    public static void func2() throws InterruptedException {
        long big = System.currentTimeMillis();
        Thread t1 = new Thread(()->{
            long b = 0;
        for(long i = 0;i< 10_0000_0000 / 2;i++){
            b++;
        }
        });
        t1.start();
        Thread t2 = new Thread(()->{
            long c = 0;
            for(long i = 0;i<10_0000_0000/ 2;i++){
                c++;
            }
        });
        t2.start();
        t1.join();
        t2.join();
        long end = System.currentTimeMillis();
        System.out.println("并行執(zhí)行消耗時間:" + (end - big) + "ms");
    }
    public static void main(String[] args) throws InterruptedException {
        func1();//串行執(zhí)行
        func2();//并行執(zhí)行
    }
}

在這里插入圖片描述

我們可以很明顯的看出串行時間要比并行時間長的多,串行時間幾乎是并行時間的2倍。

在這里插入圖片描述

Thread類的其他屬性和方法

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

屬性獲取方法
IDgetId()
名稱getName()
狀態(tài)getState()
優(yōu)先級getPriority()
是否后臺線程isDaemon()
線程是否存活isAlive()
線程是否被中斷isinterrupted()
  • ID是線程唯一的標識,不同的線程之間不會重復(fù)
  • 名稱是各種調(diào)試工具用到的
  • 狀態(tài)標識當(dāng)前線程的一種情況
  • 優(yōu)先級高的線程,理論上更容易被執(zhí)行到
  • 是否存活簡單理解為run()方法是否執(zhí)行結(jié)束

給一個線程起名字

Thread(String name) 這個東西是給thread對象起一個名字,具體起什么名字和線程的執(zhí)行效率無關(guān),起名字主要依靠于程序員,方便程序員在后期進行調(diào)試。

public class TestDemo17 {
    public static void main(String[] args) {
        //給線程器名字
        Thread t1 = new Thread(()->{
            while(true) {
                System.out.println("hello thread1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"thread1");

        Thread t2 = new Thread(()->{
            while(true) {
                System.out.println("hello thread2");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"thread2");
        t1.start();
        t2.start();
    }
}

那么怎樣才能看到,我們定義好的線程名字呢?

注意:當(dāng)我們要查看線程名字的時候,程序必須要正在執(zhí)行,否則我們查找不到對應(yīng)的線程名字。

判斷一個線程是否存活

簡單的說就是操作系統(tǒng)中我們創(chuàng)建出來的線程是否還存在

Thread t 的生命周期和操作系統(tǒng)中對應(yīng)的線程的生命周期并不是完全一致的。

我們在定義一個線程類后,在調(diào)用t.start()方法之前,操作系統(tǒng)中是沒有我們創(chuàng)建出來的線程的。在線程類中的run()方法執(zhí)行完之后,我們在操作系統(tǒng)中創(chuàng)建出來的線程就被銷毀了!但是線程t對象還存在。

  • 總而言之,在調(diào)用t.start()方法之前,在執(zhí)行run()方法之后,此時操作系統(tǒng)中是沒有我們創(chuàng)建出來的線程的。
  • 在調(diào)用t.start()方法之后,在指向run()方法之前,此時操作系統(tǒng)中存在我們創(chuàng)建出來的線程 判斷該線程是由是后臺線程

如果一個線程是后臺線程,那么這個線程就不會進行進程退出

如果一個線程是前臺線程,那么這個這個線程就會影響到進程的退出。我們以上的代碼在創(chuàng)建線程,那些線程都是前臺線程,假如現(xiàn)在有前臺線程t1,t2, 現(xiàn)在即使main線程執(zhí)行結(jié)束,但是此時還不可以退出線程,必須要將t1,t2線程執(zhí)行結(jié)束之后,整個線程才會結(jié)束。

假如現(xiàn)在有兩個線程t1,t2,它們都是后臺線程,那么如果現(xiàn)在main線程執(zhí)行結(jié)束,整個進程就執(zhí)行結(jié)束,此時我們會強制停止t1,t2線程。

public class TestDemo18 {
    public static void main(String[] args) {
        Thread t = new Thread(()->{
            System.out.println("hello thread");
        });
        t.start();
        System.out.println(t.isDaemon());
    }
}
//因為我們創(chuàng)建的是一個前臺線程,所以返回false

Thread的其他常見屬性

創(chuàng)建線程

創(chuàng)建線程:定義出一個線程類,然后啟動線程t.start(),其中start()方法決定系統(tǒng)是不是真的創(chuàng)建出線程。

在這里插入圖片描述

線程的中斷

中斷線程簡單的可以理解成為就是讓該線程中的run()方法執(zhí)行結(jié)束。還有一個特殊的就是main線程,如果想要中斷main線程,那么就需要把main線程執(zhí)行完。

中斷線程方法一:設(shè)置一個標志位

public class TestDemo21 {
    public static void main(String[] args) {
        Thread t = new Thread(()->{
           while(!Thread.currentThread().isInterrupted()) {
               System.out.println("hello thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        //啟動t線程
        t.start();
        //在main線程中中斷t線程
        //5s之后中斷t線程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
    }
}

運行結(jié)果:當(dāng)t線程中的sout語句被執(zhí)行5次之后,線程停止。

上面的這種寫法不夠嚴謹,只適用于該場合,如果化作是別的代碼場合的話,有可能不會終止線程。

這里用一種較好的方法,使用Thread類中自帶的檢查線程是否斷開。

Thread.interrputed() 這是一個靜態(tài)方法 Thread.currentThread().isinterrupted() 其中Thread.cerrentThread()可以獲得線程的引用。

t.interrupted()用于中斷線程

public class TestDemo21 {
    public static void main(String[] args) {
        Thread t = new Thread(()->{
           while(!Thread.currentThread().isInterrupted()) {
               System.out.println("hello thread");
               try {
                   Thread.sleep(1000);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        //啟動t線程
        t.start();
        //在main線程中中斷t線程
        //5s之后中斷t線程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
    }
}

在這里插入圖片描述

在這里插入圖片描述

在我們上邊中斷線程,判斷標志位的時候,我們使用的是第三種方法。設(shè)置標志位的時候使用的是第一種方法。

在我們的日常開發(fā)中,經(jīng)常會用到Thread.currentThread().isInterrupted()來判斷標志位,判斷該線程是否被中斷。

還有一種方法判斷標志位,但是它是一個靜態(tài)方法,只能判斷一個類中只有一個線程的情況下,這個方法就是Thread.isinterrupted()方法。

Thread.currentThread().isinterrupted()這個方法判斷的是Thread的普通成員,每個實例都有一個標志位。

在我們以后就無腦使用Thread.currentThread().isInterrupted()方法,判斷線程是否中斷(標志位)

線程的等待

在前面我們也介紹到j(luò)oin()方法,這個方法就是讓線程與線程之間,有了一定的執(zhí)行順序。我們知道在多線程中的調(diào)度是隨機的,不確定的,多線程的執(zhí)行靠調(diào)度器安排,該調(diào)度器的安排是隨機的,不規(guī)律的。其實線程等待就是一個行之有效的方法,實際上就是控制線程執(zhí)行的先后順序。

public class TestDemo22 {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> public static void main(String[] args) throws InterruptedException {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> Thread t = new Thread(()->{<!--{C}%3C!%2D%2D%20%2D%2D%3E--> for(int i = 0;i<5;i++){<!--{C}%3C!%2D%2D%20%2D%2D%3E--> System.out.println("hello thread"); try {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> Thread.sleep(1000); } catch (InterruptedException e) {<!--{C}%3C!%2D%2D%20%2D%2D%3E--> e.printStackTrace(); } } }); t.start(); t.join();//main線程調(diào)用t.join()方法,main線程就處于阻塞狀態(tài),當(dāng)t線程執(zhí)行完后,喚醒main線程執(zhí)行后序代碼 System.out.println("hello main"); }}

在這里插入圖片描述

獲取線程的引用

使用方法Thread.currentTread()就可以該線程的實例。

public class TestDemo23 {
    public static void main(String[] args) {
         Thread t = new Thread(){
             @Override
             public void run() {
                 //獲取當(dāng)前線程的引用
                 //System.out.println(Thread.currentThread().getName());
                 //因為當(dāng)前使用的匿名內(nèi)部類是繼承自Thread類,Thread就是該匿名內(nèi)部類的父類,所以可以通過this得到當(dāng)前Thread的實例
                 System.out.println(this.getName());
             }
         };
         t.start();
    }
}

在這里插入圖片描述

線程的休眠

其實線程休眠就是調(diào)用Thread.sleep()方法。

回顧之前的學(xué)習(xí)內(nèi)容,我們知道我們使用PCB描述一個進程,使用雙向鏈表來組織進程。這種說法是針對一個進程中只有一個線程的情況下。

那么如果一個進程中有多個線程存在,那么每個線程就有一個PCB,那么每個進程都會有一組PCB,

PCB上有一個字段為tgroupId,這個id就相當(dāng)于是進程的id,進程中的每個線程的tgroupId都是相同的。

那么進程控制塊(process contral block)和線程有什么關(guān)系呢?

其實在linux中是不區(qū)分進程和線程的,所謂的線程是程序員自己搞出來的,實際上linux只認進程控制塊(PCB),實際上線程就相當(dāng)于一個輕量級進程。

在這里插入圖片描述

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

相關(guān)文章

  • 關(guān)于elasticsearch的match_phrase_prefix查詢詳解

    關(guān)于elasticsearch的match_phrase_prefix查詢詳解

    這篇文章主要介紹了關(guān)于elasticsearch的match_phrase_prefix查詢問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • jdk1.8的環(huán)境配置過程

    jdk1.8的環(huán)境配置過程

    Java平臺由Java虛擬機和Java應(yīng)用程序接口搭建,Java語言則是進入這個平臺的通道,用Java語言編寫并編譯的程序可以運行在這個平臺上,本文給大家講解jdk1.8的環(huán)境配置過程,感興趣的朋友跟隨小編一起看看吧
    2022-11-11
  • java實現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼)

    java實現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼)

    為避免繁瑣的注冊登陸,很多平臺和網(wǎng)站都會實現(xiàn)三方登陸的功能,增強用戶的粘性。這篇文章主要介紹了java實現(xiàn)微信掃碼登錄第三方網(wǎng)站功能(原理和代碼),避免做微信登錄開發(fā)的朋友們少走彎路
    2022-12-12
  • 如何優(yōu)雅的拋出Spring Boot注解的異常詳解

    如何優(yōu)雅的拋出Spring Boot注解的異常詳解

    這篇文章主要給大家介紹了關(guān)于如何優(yōu)雅的拋出Spring Boot注解的異常的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • JAVA按字節(jié)讀取文件的簡單實例

    JAVA按字節(jié)讀取文件的簡單實例

    下面小編就為大家?guī)硪黄狫AVA按字節(jié)讀取文件的簡單實例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-08-08
  • Java集合和數(shù)組的區(qū)別

    Java集合和數(shù)組的區(qū)別

    本文主要介紹了Java集合和數(shù)組的區(qū)別。具有很好的參考價值,下面跟著小編一起來看下吧
    2017-02-02
  • 基于Java編寫簡單的Excel工具類

    基于Java編寫簡單的Excel工具類

    這篇文章主要為大家詳細介紹了如何基于Java編寫簡單的Excel工具類,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考下
    2024-02-02
  • Java中的volatile關(guān)鍵字解析

    Java中的volatile關(guān)鍵字解析

    這篇文章主要介紹了Java中的volatile關(guān)鍵字解析,Java內(nèi)存模型規(guī)定了所有的變量都存儲在主內(nèi)存中,每個線程都有自己的工作內(nèi)存,線程的工作內(nèi)存保存了該線程使用到的變量的是主內(nèi)存副本的拷貝,需要的朋友可以參考下
    2023-11-11
  • springboot項目部署到寶塔的詳細圖文教程

    springboot項目部署到寶塔的詳細圖文教程

    網(wǎng)上關(guān)于寶塔運行springBoot的東西說有點迷糊,但是有一句話很重要,Spring boot項目只需要JDK環(huán)境即可部署成功,下面這篇文章主要給大家介紹了關(guān)于springboot項目部署到寶塔的詳細圖文教程,需要的朋友可以參考下
    2023-05-05
  • java中將一個List等分成n個list的工具方法(推薦)

    java中將一個List等分成n個list的工具方法(推薦)

    下面小編就為大家?guī)硪黄猨ava中將一個List等分成n個list的工具方法(推薦)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03

最新評論