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

Java線程中的常見方法(start方法和run方法)

 更新時(shí)間:2022年07月29日 16:10:02   作者:0x3f3f3f3f  
這篇文章主要介紹了Java線程中的常見方法(start方法和run方法),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下

start方法和run方法

$start()$方法用來啟動(dòng)一個(gè)線程,這時(shí)此線程處于就緒(可運(yùn)行)狀態(tài),并沒有運(yùn)行,一旦得到$cpu$時(shí)間片,就開始執(zhí)行$run()$方法。而直接調(diào)用$run()$方法,僅僅只是調(diào)用了一個(gè)類里的方法,其本質(zhì)上還是在當(dāng)前線程中執(zhí)行的,因此只有使用$start()$方法來調(diào)用$run()$方法才能實(shí)現(xiàn)真正的多線程。

示例代碼

@Slf4j(topic = "c.Test4")
public class Test4 {
    public static void main(String[] args) {
        Thread t1 = new Thread("t1"){
            @Override
            public void run() {
                log.debug("running");
            }
        };
        t1.run();
    }
}

上述代碼是直接調(diào)用的$run()$方法??梢钥吹酱蛴⌒畔⒗?,是$main$線程執(zhí)行了這個(gè)方法。

@Slf4j(topic = "c.Test4")
public class Test4 {
    public static void main(String[] args) {
        Thread t1 = new Thread("t1"){
            @Override
            public void run() {
                log.debug("running");
            }
        };
        t1.start();
    }
}

而如果使用$start()$方法啟動(dòng),才是真正的由$t1$線程執(zhí)行的$run$方法。

注意

需要注意的是,當(dāng)$Thread$對(duì)象調(diào)用了$start()$方法后,就會(huì)進(jìn)入就緒狀態(tài),處于就緒狀態(tài)時(shí)無法再調(diào)用$start()$方法,否則就會(huì)拋出$IllegalThreadStateException$異常,如下代碼所示

@Slf4j(topic = "c.Test4")
public class Test4 {
    public static void main(String[] args) {
        Thread t1 = new Thread("t1"){
            @Override
            public void run() {
                log.debug("running");
            }
        };
        t1.start();
        t1.start();
    }
}

異常信息:

sleep方法與yield方法

sleep

  • 調(diào)用$sleep()$方法會(huì)讓當(dāng)前線程從$Running$狀態(tài)變成$Time Waiting$狀態(tài)(阻塞)
  • 其它線程可以使用$interrupt$方法打斷正在睡眠的線程,此時(shí)$sleep$方法會(huì)拋出InterruptedException
  • 睡眠結(jié)束后的線程未必會(huì)立刻得到執(zhí)行
  • 建議用$TimeUnit$的$sleep$代替$Thread$的$sleep$來獲得更好的可讀性示例代碼
@Slf4j(topic = "c.Test5")
public class Test5 {
    public static void main(String[] args) {
        Thread t1 = new Thread("t1"){
            @Override
            public void run() {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t1.start();
        log.debug("t1 state {}", t1.getState());
        //讓主線程休眠500ms
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        log.debug("t1 state {}", t1.getState());
    }
}
//17:13:21.729 [main] DEBUG c.Test5 - t1 state RUNNABLE
//17:13:22.245 [main] DEBUG c.Test5 - t1 state TIMED_WAITING

上述代碼中,首先啟動(dòng)$t1$線程,此時(shí)打印線程的狀態(tài)應(yīng)該是處于$RUNNABLE$狀態(tài),而讓主線程休眠是防止主線程先執(zhí)行打印,但是還未進(jìn)入到$sleep()$狀態(tài)。當(dāng)執(zhí)行到$run()$里邊的$sleep$方法時(shí),線程進(jìn)入$TIMED WAITING$狀態(tài)

@Slf4j(topic = "c.Test6")
public class Thread6 {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread("t1") {
            @Override
            public void run() {
                try {
                    log.debug("enter sleep");
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    log.debug("wake up");
                    e.printStackTrace();
                }
            }
        };
        t1.start();
        Thread.sleep(1000);
        log.debug("interrupt t1");
        //被喚醒
        t1.interrupt();
    }
}

執(zhí)行結(jié)果

上述代碼中,當(dāng)$start$方法啟動(dòng)后,$t1$線程進(jìn)入睡眠狀態(tài),打印提示信息,睡眠時(shí)間為$2s$,在$main$線程中睡眠$1s$后打斷$t1$線程的睡眠,提示打斷信息,并且調(diào)用$interrupt()$方法,此時(shí)線程被打斷,拋出異常。

$TimeUnit$類中新增了以什么單位去睡眠,可讀性更好,但是本質(zhì)上沒區(qū)別,只是進(jìn)行了單位換算

TimeUnit.SECONDS.sleep(1);//該語句作用是睡眠一秒

yield

調(diào)用$yield$會(huì)讓當(dāng)前進(jìn)程從$Running$進(jìn)入到$Runnable$就緒狀態(tài),然后調(diào)度執(zhí)行其他線程具體的實(shí)現(xiàn)依賴于操作系統(tǒng)的任務(wù)調(diào)度器,(即當(dāng)任務(wù)調(diào)度器中沒有其他任務(wù)時(shí),即使讓出$cpu$,也會(huì)繼續(xù)執(zhí)行該線程)$sleep$執(zhí)行后是進(jìn)入阻塞狀態(tài),此時(shí)睡眠時(shí)間不結(jié)束,就不會(huì)分配$cpu$給該線程,但是$yield$是進(jìn)入就緒狀態(tài),即如果沒有其他線程需要執(zhí)行,那么還會(huì)給該線程分配時(shí)間片,這是$sleep$和$yield$的最大區(qū)別線程優(yōu)先級(jí)

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

會(huì)提示調(diào)度器優(yōu)先調(diào)度該線程,但它僅僅是一個(gè)提示,調(diào)度器可以忽略他
如果$cpu$比較忙,那么優(yōu)先級(jí)高的會(huì)獲得更多的時(shí)間片,可$cpu$空閑時(shí),優(yōu)先級(jí)幾乎沒有

sleep的應(yīng)用-防止cpu占用100%

在沒有利用$cpu$來計(jì)算時(shí),不要讓$while(true)$空轉(zhuǎn)浪費(fèi)$cpu$,這時(shí)可以可以使用$yield$或者$sleep$來讓$cpu$的使用權(quán)交給其他程序

while (true) {
    try {
        Thread.sleep(50);
    } catch (InterruptedException e) {
        e.printStackTrace();
  }
}

可以使用$wait$或者條件變量達(dá)到類似的效果
不同的是后兩者都需要加鎖,并且需要相應(yīng)的喚醒操作,一般適用于要進(jìn)行同步的場景
$sleep$適用于無需鎖同步的場景

join方法

以下程序的打印結(jié)果:

@Slf4j(topic = "c.Test6")
public class Test6 {
    static int r = 0;
    public static void main(String[] args) {
        test();
    }
    private static void test() {
        log.debug("開始");
        Thread t = new Thread("t1") {
            @Override
            public void run() {
                log.debug("開始");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                log.debug("結(jié)束");
                r = 10;
            }
        };
        t.start();
        log.debug("r的值是{}", r);
        log.debug("結(jié)束");
    }
}

因?yàn)橹骶€程和$t1$線程是并行的,$t1$線程需要$1s$后才能計(jì)算出$r$的值,而主線程一開始就要打印出$r$的值,因此打印的值為0

解決方法:

在$t.start();$后邊加上$t.join();$即可。$join$的作用是等待某線程運(yùn)行結(jié)束。
以調(diào)用方的角度來說,需要等待結(jié)果返回才能繼續(xù)執(zhí)行就是同步,不需要等待返回結(jié)果就能繼續(xù)執(zhí)行的就是異步。

因此$join$方法實(shí)際上是讓其同步執(zhí)行

有實(shí)效的等待

$join(毫秒)$方法里可以有一個(gè)參數(shù)是傳入等待的時(shí)間,如果線程執(zhí)行時(shí)間大于等待時(shí)間,則等待時(shí)間到了之后,就會(huì)停止等待。如果線程執(zhí)行時(shí)間小于等待時(shí)間,則線程執(zhí)行完畢之后,等待也會(huì)跟著結(jié)束。不會(huì)把設(shè)置的等待時(shí)間過完。

interrupt方法

打斷$sleep, wait, join$的線程,即打斷阻塞狀態(tài)的線程
打斷$sleep$的線程,會(huì)清空打斷狀態(tài)

@Slf4j(topic = "c.Test7")
public class Test7 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread("t1"){
            @Override
            public void run() {
                log.debug("sleep...");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };
        t.start();
        Thread.sleep(1000);
        log.debug("interrupt");
        t.interrupt();
        log.debug("打斷標(biāo)記: {}", t.isInterrupted());
    }
}

打斷正常運(yùn)行的線程,不會(huì)清空打斷狀態(tài)

因此我們可以在線程中判斷打斷標(biāo)記,來決定是否被打斷,以及執(zhí)行被打斷之前的收尾工作。

@Slf4j(topic = "c.Test8")
public class Test8 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread("t1"){
            @Override
            public void run() {
                while (true) {
                    if (Thread.currentThread().isInterrupted()) {
                        log.debug("線程被打斷了");
                        break;
                    }
                }
            }
        };
        t.start();
        Thread.sleep(1000);
        log.debug("interrupt");
        t.interrupt();
    }
}

守護(hù)線程

默認(rèn)情況下,$java$需要等待所有線程都運(yùn)行結(jié)束,才會(huì)結(jié)束。有一種特殊的線程叫做守護(hù)線程,只要其他非守護(hù)線程運(yùn)行結(jié)束了,即使守護(hù)線程的代碼沒有執(zhí)行完畢,也會(huì)強(qiáng)制結(jié)束。

@Slf4j(topic = "c.Test10")
public class Test10 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread("t1") {
            @Override
            public void run() {
                while (true) {

                }
            }
        };
        //設(shè)置線程為守護(hù)線程
        t.setDaemon(true);
        t.start();
        Thread.sleep(1000);
        log.debug("主線程結(jié)束");
    }
}

如果不把$t$設(shè)置為守護(hù)線程,則因?yàn)榫€程內(nèi)部的死循環(huán),導(dǎo)致程序不會(huì)結(jié)束運(yùn)行。

到此這篇關(guān)于Java線程中的常見方法(start方法和run方法)的文章就介紹到這了,更多相關(guān)Java線程方法內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java Swing組件單選框JRadioButton用法示例

    Java Swing組件單選框JRadioButton用法示例

    這篇文章主要介紹了Java Swing組件單選框JRadioButton用法,結(jié)合具體實(shí)例形式分析了Swing單選框JRadioButton的使用方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2017-11-11
  • Mybatis-Plus實(shí)現(xiàn)多主鍵批量保存及更新詳情

    Mybatis-Plus實(shí)現(xiàn)多主鍵批量保存及更新詳情

    這篇文章主要介紹了Mybatis-Plus實(shí)現(xiàn)多主鍵批量保存及更新詳情,文章通過圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-09-09
  • 在SpringBoot當(dāng)中使用Thymeleaf視圖解析器的詳細(xì)教程

    在SpringBoot當(dāng)中使用Thymeleaf視圖解析器的詳細(xì)教程

    Thymeleaf是一款開源的模板引擎,它允許前端開發(fā)者使用HTML與XML編寫動(dòng)態(tài)網(wǎng)頁,hymeleaf的主要特點(diǎn)是將表達(dá)式語言嵌入到HTML結(jié)構(gòu)中,它支持Spring框架,使得在Spring MVC應(yīng)用中集成非常方便,本文給大家介紹了在SpringBoot當(dāng)中使用Thymeleaf視圖解析器的詳細(xì)教程
    2024-09-09
  • 在日志中記錄Java異常信息的正確姿勢分享

    在日志中記錄Java異常信息的正確姿勢分享

    這篇文章主要介紹了在日志中記錄Java異常信息的正確姿勢,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Callable實(shí)現(xiàn)多線程步驟詳解

    Callable實(shí)現(xiàn)多線程步驟詳解

    這篇文章主要介紹了Callable實(shí)現(xiàn)多線程步驟詳解,Callable是一個(gè)接口,用于實(shí)現(xiàn)多線程,與實(shí)現(xiàn)Runnable類似,但是功能更強(qiáng)大,該方法可以在任務(wù)結(jié)束后提供一個(gè)返回值,需要的朋友可以參考下
    2023-10-10
  • 淺談Java變量賦值運(yùn)算符及相關(guān)實(shí)例

    淺談Java變量賦值運(yùn)算符及相關(guān)實(shí)例

    這篇文章主要介紹了Java賦值運(yùn)算符的一些知識(shí),需要的朋友可以參考下。
    2017-09-09
  • Servlet+JDBC實(shí)現(xiàn)登陸功能的小例子(帶驗(yàn)證碼)

    Servlet+JDBC實(shí)現(xiàn)登陸功能的小例子(帶驗(yàn)證碼)

    這篇文章主要介紹了Servlet+JDBC實(shí)現(xiàn)登陸功能的小例子(帶驗(yàn)證碼),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Java的MyBatis框架中實(shí)現(xiàn)多表連接查詢和查詢結(jié)果分頁

    Java的MyBatis框架中實(shí)現(xiàn)多表連接查詢和查詢結(jié)果分頁

    這篇文章主要介紹了Java的MyBatis框架中實(shí)現(xiàn)多表連接查詢和查詢結(jié)果分頁,借助MyBatis框架中帶有的動(dòng)態(tài)SQL查詢功能可以比普通SQL查詢做到更多,需要的朋友可以參考下
    2016-04-04
  • Java中16條的代碼規(guī)范

    Java中16條的代碼規(guī)范

    如何更規(guī)范化編寫Java 代碼的重要性想必毋需多言,其中最重要的幾點(diǎn)當(dāng)屬提高代碼性能、使代碼遠(yuǎn)離Bug、令代碼更優(yōu)雅,
    2021-07-07
  • 手把手教你在eclipse創(chuàng)建第一個(gè)java?web項(xiàng)目并運(yùn)行

    手把手教你在eclipse創(chuàng)建第一個(gè)java?web項(xiàng)目并運(yùn)行

    Eclipse是用來做開發(fā)的自由集成開發(fā)環(huán)境,這也是很多java程序員會(huì)使用的開發(fā)環(huán)境,所以可以使用eclipse創(chuàng)建javaweb項(xiàng)目,下面這篇文章主要給大家介紹了關(guān)于如何在eclipse創(chuàng)建第一個(gè)java?web項(xiàng)目并運(yùn)行的相關(guān)資料,需要的朋友可以參考下
    2023-02-02

最新評(píng)論

鸡西市| 天祝| 五寨县| 留坝县| 邓州市| 永德县| 嘉义市| 聂荣县| 明溪县| 新绛县| 闽侯县| 紫阳县| 泸溪县| 敦煌市| 叙永县| 明水县| 井研县| 冀州市| 万州区| 凌源市| 合川市| 织金县| 临江市| 丰城市| 黄冈市| 岢岚县| 伊宁市| 运城市| 宜川县| 赤水市| 栖霞市| 东安县| 桃园市| 万源市| 清丰县| 郸城县| 常德市| 左云县| 林西县| 射洪县| 巴林左旗|