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

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

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

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

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

創(chuàng)建線程

方法一:繼承Thread類

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

在這里插入圖片描述

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

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

在這里插入圖片描述

在這里插入圖片描述

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

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

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

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

//Runnable其實(shí)就是描述一個(gè)任務(wù)
//創(chuàng)建一個(gè)類,實(shí)現(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實(shí)例傳給Thread實(shí)例
        Thread t = new Thread(new MyThread2());
        t.start();
    }
}

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

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

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

    }
}

使用線程的好處

為了更方便的體現(xiàn)出多線程的好處,在這里我們從0開始自增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í)間長的多,串行時(shí)間幾乎是并行時(shí)間的2倍。

在這里插入圖片描述

Thread類的其他屬性和方法

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

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

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

Thread(String name) 這個(gè)東西是給thread對象起一個(gè)名字,具體起什么名字和線程的執(zhí)行效率無關(guān),起名字主要依靠于程序員,方便程序員在后期進(jì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)我們要查看線程名字的時(shí)候,程序必須要正在執(zhí)行,否則我們查找不到對應(yīng)的線程名字。

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

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

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

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

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

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

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

假如現(xiàn)在有兩個(gè)線程t1,t2,它們都是后臺(tái)線程,那么如果現(xiàn)在main線程執(zhí)行結(jié)束,整個(gè)進(jìn)程就執(zhí)行結(jié)束,此時(shí)我們會(huì)強(qiáng)制停止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());
    }
}
//因?yàn)槲覀儎?chuàng)建的是一個(gè)前臺(tái)線程,所以返回false

Thread的其他常見屬性

創(chuàng)建線程

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

在這里插入圖片描述

線程的中斷

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

中斷線程方法一:設(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線程
        t.start();
        //在main線程中中斷t線程
        //5s之后中斷t線程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
    }
}

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

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

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

Thread.interrputed() 這是一個(gè)靜態(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();
               }
           }
        });
        //啟動(dòng)t線程
        t.start();
        //在main線程中中斷t線程
        //5s之后中斷t線程
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t.interrupt();
    }
}

在這里插入圖片描述

在這里插入圖片描述

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

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

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

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

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

線程的等待

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

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());
                 //因?yàn)楫?dāng)前使用的匿名內(nèi)部類是繼承自Thread類,Thread就是該匿名內(nèi)部類的父類,所以可以通過this得到當(dāng)前Thread的實(shí)例
                 System.out.println(this.getName());
             }
         };
         t.start();
    }
}

在這里插入圖片描述

線程的休眠

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

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

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

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

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

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

在這里插入圖片描述

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

相關(guān)文章

最新評論

洪洞县| 卫辉市| 道孚县| 霍邱县| 台前县| 麟游县| 临夏市| 昭通市| 楚雄市| 武城县| 聂荣县| 京山县| 蕲春县| 娱乐| 宜宾县| 望城县| 英超| 从化市| 阿城市| 佛冈县| 永泰县| 灵台县| 宁陵县| 朝阳区| 龙泉市| 江津市| 合水县| 中牟县| 澄城县| 东乌珠穆沁旗| 峨眉山市| 遂川县| 丰县| 锡林郭勒盟| 武隆县| 汉中市| 苍溪县| 安康市| 东兰县| 林周县| 黄陵县|