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

Java中Thread類(lèi)的使用和它的屬性

 更新時(shí)間:2022年04月12日 15:38:17   作者:小小怪下士~  
在java中可以進(jìn)行多線(xiàn)程編程,在java標(biāo)準(zhǔn)庫(kù)中提供了一個(gè)Thread類(lèi),來(lái)表示線(xiàn)程操作,本文主要介紹了Java中Thread類(lèi)的使用和它的屬性,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

在java中可以進(jìn)行多線(xiàn)程編程,在java標(biāo)準(zhǔn)庫(kù)中提供了一個(gè)Thread類(lèi),來(lái)表示線(xiàn)程操作。Thread類(lèi)可以視為java標(biāo)準(zhǔn)庫(kù)提供的一組解決多線(xiàn)程編程的一組API.

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

創(chuàng)建線(xiàn)程

方法一:繼承Thread類(lèi)

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

在這里插入圖片描述

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

class MyThread3 extends Thread{
    @Override
    public void run() { //定義一個(gè)線(xiàn)程類(lèi)
        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();//啟動(dòng)t線(xiàn)程
        while(true){
            System.out.println("hello main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

在這里插入圖片描述

在這里插入圖片描述

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

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

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

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

//Runnable其實(shí)就是描述一個(gè)任務(wù)
//創(chuàng)建一個(gè)類(lèi),實(shí)現(xiàn)Runnable接口,重寫(xiě)Runnable類(lèi)中的run方法,在run()方法中,描述的是該線(xiàn)程要指向的哪些任務(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)建線(xiàn)程,把創(chuàng)建好的Runnable實(shí)例傳給Thread實(shí)例
        Thread t = new Thread(new MyThread2());
        t.start();
    }
}

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

方法三其實(shí)是方法一個(gè)的翻版,就是把上面的兩種代碼,改成了匿名內(nèi)部類(lè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表達(dá)式

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

    }
}

使用線(xiàn)程的好處

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

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("串行消耗時(shí)間:" + (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í)行消耗時(shí)間:" + (end - big) + "ms");
    }
    public static void main(String[] args) throws InterruptedException {
        func1();//串行執(zhí)行
        func2();//并行執(zhí)行
    }
}

在這里插入圖片描述

我們可以很明顯的看出串行時(shí)間要比并行時(shí)間長(zhǎng)的多,串行時(shí)間幾乎是并行時(shí)間的2倍。

在這里插入圖片描述

Thread類(lèi)的其他屬性和方法

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

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

給一個(gè)線(xiàn)程起名字

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

public class TestDemo17 {
    public static void main(String[] args) {
        //給線(xiàn)程器名字
        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();
    }
}

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

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

判斷一個(gè)線(xiàn)程是否存活

簡(jiǎn)單的說(shuō)就是操作系統(tǒng)中我們創(chuàng)建出來(lái)的線(xiàn)程是否還存在

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

我們?cè)诙x一個(gè)線(xiàn)程類(lèi)后,在調(diào)用t.start()方法之前,操作系統(tǒng)中是沒(méi)有我們創(chuàng)建出來(lái)的線(xiàn)程的。在線(xiàn)程類(lèi)中的run()方法執(zhí)行完之后,我們?cè)诓僮飨到y(tǒng)中創(chuàng)建出來(lái)的線(xiàn)程就被銷(xiāo)毀了!但是線(xiàn)程t對(duì)象還存在。

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

如果一個(gè)線(xiàn)程是后臺(tái)線(xiàn)程,那么這個(gè)線(xiàn)程就不會(huì)進(jìn)行進(jìn)程退出

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

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

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());
    }
}
//因?yàn)槲覀儎?chuàng)建的是一個(gè)前臺(tái)線(xiàn)程,所以返回false

Thread的其他常見(jiàn)屬性

創(chuàng)建線(xiàn)程

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

在這里插入圖片描述

線(xiàn)程的中斷

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

中斷線(xiàn)程方法一:設(shè)置一個(gè)標(biāo)志位

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();
               }
           }
        });
        //啟動(dòng)t線(xiàn)程
        t.start();
        //在main線(xiàn)程中中斷t線(xiàn)程
        //5s之后中斷t線(xiàn)程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
    }
}

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

上面的這種寫(xiě)法不夠嚴(yán)謹(jǐn),只適用于該場(chǎng)合,如果化作是別的代碼場(chǎng)合的話(huà),有可能不會(huì)終止線(xiàn)程。

這里用一種較好的方法,使用Thread類(lèi)中自帶的檢查線(xiàn)程是否斷開(kāi)。

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

t.interrupted()用于中斷線(xiàn)程

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();
               }
           }
        });
        //啟動(dòng)t線(xiàn)程
        t.start();
        //在main線(xiàn)程中中斷t線(xiàn)程
        //5s之后中斷t線(xiàn)程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
    }
}

在這里插入圖片描述

在這里插入圖片描述

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

在我們的日常開(kāi)發(fā)中,經(jīng)常會(huì)用到Thread.currentThread().isInterrupted()來(lái)判斷標(biāo)志位,判斷該線(xiàn)程是否被中斷。

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

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

在我們以后就無(wú)腦使用Thread.currentThread().isInterrupted()方法,判斷線(xiàn)程是否中斷(標(biāo)志位)

線(xiàn)程的等待

在前面我們也介紹到j(luò)oin()方法,這個(gè)方法就是讓線(xiàn)程與線(xiàn)程之間,有了一定的執(zhí)行順序。我們知道在多線(xiàn)程中的調(diào)度是隨機(jī)的,不確定的,多線(xiàn)程的執(zhí)行靠調(diào)度器安排,該調(diào)度器的安排是隨機(jī)的,不規(guī)律的。其實(shí)線(xiàn)程等待就是一個(gè)行之有效的方法,實(shí)際上就是控制線(xiàn)程執(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線(xiàn)程調(diào)用t.join()方法,main線(xiàn)程就處于阻塞狀態(tài),當(dāng)t線(xiàn)程執(zhí)行完后,喚醒main線(xiàn)程執(zhí)行后序代碼 System.out.println("hello main"); }}

在這里插入圖片描述

獲取線(xiàn)程的引用

使用方法Thread.currentTread()就可以該線(xiàn)程的實(shí)例。

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

在這里插入圖片描述

線(xiàn)程的休眠

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

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

那么如果一個(gè)進(jìn)程中有多個(gè)線(xiàn)程存在,那么每個(gè)線(xiàn)程就有一個(gè)PCB,那么每個(gè)進(jìn)程都會(huì)有一組PCB,

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

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

其實(shí)在linux中是不區(qū)分進(jìn)程和線(xiàn)程的,所謂的線(xiàn)程是程序員自己搞出來(lái)的,實(shí)際上linux只認(rèn)進(jìn)程控制塊(PCB),實(shí)際上線(xiàn)程就相當(dāng)于一個(gè)輕量級(jí)進(jìn)程。

在這里插入圖片描述

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

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

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

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

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

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

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

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

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

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

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

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

    基于Java編寫(xiě)簡(jiǎn)單的Excel工具類(lèi)

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

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

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

    springboot項(xiàng)目部署到寶塔的詳細(xì)圖文教程

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

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

    下面小編就為大家?guī)?lái)一篇java中將一個(gè)List等分成n個(gè)list的工具方法(推薦)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-03-03
  • 最新評(píng)論