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

聊聊Java中是什么方法導(dǎo)致的線程阻塞

 更新時(shí)間:2021年02月20日 09:52:34   作者:Chin_style  
這篇文章主要介紹了聊聊Java中是什么方法導(dǎo)致的線程阻塞,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

一、為什么引入線程阻塞機(jī)制?

為了解決對(duì)共享存儲(chǔ)區(qū)的訪問(wèn)沖突,Java 引入了同步機(jī)制,現(xiàn)在讓我們來(lái)考察多個(gè)線程對(duì)共享資源的訪問(wèn),顯然同步機(jī)制已經(jīng)不夠了,因?yàn)樵谌我鈺r(shí)刻所要求的資源不一定已經(jīng)準(zhǔn)備好了被訪問(wèn),反過(guò)來(lái),同一時(shí)刻準(zhǔn)備好了的資源也可能不止一個(gè)。為了解決這種情況下的訪問(wèn)控制問(wèn)題,Java 引入了對(duì)阻塞機(jī)制的支持

阻塞指的是暫停一個(gè)線程的執(zhí)行以等待某個(gè)條件發(fā)生(如某資源就緒),學(xué)過(guò)操作系統(tǒng)的同學(xué)對(duì)它一定已經(jīng)很熟悉了。Java 提供了大量方法來(lái)支持阻塞,下面讓我們逐一分析。

二、Java中實(shí)現(xiàn)線程阻塞的方法:

(1)線程睡眠:Thread.sleep (long millis)方法,使線程轉(zhuǎn)到阻塞狀態(tài)。millis參數(shù)設(shè)定睡眠的時(shí)間,以毫秒為單位。當(dāng)睡眠結(jié)束后,就轉(zhuǎn)為就緒(Runnable)狀態(tài)。sleep()平臺(tái)移植性好。

(2)線程等待:Object類(lèi)中的wait()方法,導(dǎo)致當(dāng)前的線程等待,直到其他線程調(diào)用此對(duì)象的 notify() 喚醒方法。這個(gè)兩個(gè)喚醒方法也是Object類(lèi)中的方法,行為等價(jià)于調(diào)用 wait() 一樣。wait() 和 notify() 方法:兩個(gè)方法配套使用,wait() 使得線程進(jìn)入阻塞狀態(tài),它有兩種形式,一種允許 指定以毫秒為單位的一段時(shí)間作為參數(shù),另一種沒(méi)有參數(shù),前者當(dāng)對(duì)應(yīng)的 notify() 被調(diào)用或者超出指定時(shí)間時(shí)線程重新進(jìn)入可執(zhí)行狀態(tài),后者則必須對(duì)應(yīng)的 notify() 被調(diào)用.

(3)線程禮讓?zhuān)琓hread.yield() 方法,暫停當(dāng)前正在執(zhí)行的線程對(duì)象,把執(zhí)行機(jī)會(huì)讓給相同或者更高優(yōu)先級(jí)的線程。yield() 使得線程放棄當(dāng)前分得的 CPU 時(shí)間,但是不使線程阻塞,即線程仍處于可執(zhí)行狀態(tài),隨時(shí)可能再次分得 CPU 時(shí)間。調(diào)用 yield() 的效果等價(jià)于調(diào)度程序認(rèn)為該線程已執(zhí)行了足夠的時(shí)間從而轉(zhuǎn)到另一個(gè)線程.

(4)線程自閉,join()方法,等待其他線程終止。在當(dāng)前線程中調(diào)用另一個(gè)線程的join()方法,則當(dāng)前線程轉(zhuǎn)入阻塞狀態(tài),直到另一個(gè)進(jìn)程運(yùn)行結(jié)束,當(dāng)前線程再由阻塞轉(zhuǎn)為就緒狀態(tài)。

(5)suspend() 和 resume() 方法:兩個(gè)方法配套使用,suspend()使得線程進(jìn)入阻塞狀態(tài),并且不會(huì)自動(dòng)恢復(fù),必須其對(duì)應(yīng)的resume() 被調(diào)用,才能使得線程重新進(jìn)入可執(zhí)行狀態(tài)。典型地,suspend() 和 resume() 被用在等待另一個(gè)線程產(chǎn)生的結(jié)果的情形:測(cè)試發(fā)現(xiàn)結(jié)果還沒(méi)有產(chǎn)生后,讓線程阻塞,另一個(gè)線程產(chǎn)生了結(jié)果后,調(diào)用 resume() 使其恢復(fù)。Thread中suspend()和resume()兩個(gè)方法在JDK1.5中已經(jīng)廢除,不再介紹。因?yàn)橛兴梨i傾向。

這里,筆者放入一張線程生命周期的經(jīng)典圖片,來(lái)幫助讀者理解,里面展示了一個(gè)線程從創(chuàng)建->運(yùn)行->阻塞->運(yùn)行->死亡的全過(guò)程:

三、常用線程名詞解釋

主線程:JVM調(diào)用程序main()所產(chǎn)生的線程。

當(dāng)前線程:這個(gè)是容易混淆的概念。一般指通過(guò)Thread.currentThread()來(lái)獲取的進(jìn)程。

后臺(tái)線程:指為其他線程提供服務(wù)的線程,也稱(chēng)為守護(hù)線程。JVM的垃圾回收線程就是一個(gè)后臺(tái)線程。用戶(hù)線程和守護(hù)線程的區(qū)別在于,是否等待主線程依賴(lài)于主線程結(jié)束而結(jié)束

前臺(tái)線程:是指接受后臺(tái)線程服務(wù)的線程,其實(shí)前臺(tái)后臺(tái)線程是聯(lián)系在一起,就像傀儡和幕后操縱者一樣的關(guān)系??苁乔芭_(tái)線程、幕后操縱者是后臺(tái)線程。由前臺(tái)線程創(chuàng)建的線程默認(rèn)也是前臺(tái)線程??梢酝ㄟ^(guò)isDaemon()和setDaemon()方法來(lái)判斷和設(shè)置一個(gè)線程是否為后臺(tái)線程。

可見(jiàn)進(jìn)程:可見(jiàn)進(jìn)程是指一些不在前臺(tái),但用戶(hù)依然可見(jiàn)的進(jìn)程,舉例來(lái)說(shuō):各種widget、輸入法等,都屬于visibe。這部分進(jìn)程雖然不在前臺(tái),但與我們的使用也是密切相關(guān),我們并不希望它被系統(tǒng)終止。

“前臺(tái)可見(jiàn)進(jìn)程服務(wù)于后臺(tái)空進(jìn)程”——這是記錄線程重要性的口訣,

重要性一次遞減即,前臺(tái)進(jìn)程>可見(jiàn)進(jìn)程>服務(wù)進(jìn)程>后臺(tái)進(jìn)程>空進(jìn)程。

線程類(lèi)的一些常用方法:

sleep(): 強(qiáng)迫一個(gè)線程睡眠N毫秒。

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

join(): 等待線程終止。

activeCount(): 程序中活躍的線程數(shù)。

enumerate(): 枚舉程序中的線程。

currentThread(): 得到當(dāng)前線程。

isDaemon(): 一個(gè)線程是否為守護(hù)線程。

setDaemon(): 設(shè)置一個(gè)線程為守護(hù)線程。(用戶(hù)線程和守護(hù)線程的區(qū)別在于,是否等待主線程依賴(lài)于主線程結(jié)束而結(jié)束)

setName(): 為線程設(shè)置一個(gè)名稱(chēng)。

wait(): 強(qiáng)迫一個(gè)線程等待。

notify(): 通知一個(gè)線程繼續(xù)運(yùn)行。

setPriority(): 設(shè)置一個(gè)線程的優(yōu)先級(jí)。

補(bǔ)充:java處理線程阻塞的小技巧

在java中我們使用多線程去處理一些業(yè)務(wù),如果業(yè)務(wù)比較復(fù)雜且當(dāng)并發(fā)量有挺大的時(shí)候,很有可能出現(xiàn)線程阻塞的問(wèn)題。

案例:

有一個(gè)觸發(fā)接口,根據(jù)觸發(fā)的信息內(nèi)部開(kāi)啟多個(gè)線程去執(zhí)行業(yè)務(wù),每個(gè)線程都會(huì)去執(zhí)行兩種業(yè)務(wù):私有業(yè)務(wù)(比如調(diào)用不同的接口)、公共業(yè)務(wù)(比如執(zhí)行存儲(chǔ)、mq發(fā)送等等),當(dāng)私有業(yè)務(wù)處理時(shí)間很快而公共業(yè)務(wù)處理時(shí)間比較長(zhǎng),這樣的情景下就可以把私有業(yè)務(wù)和公共業(yè)務(wù)分到不同線程執(zhí)行。

例如:

當(dāng)觸發(fā)了這個(gè)接口,根據(jù)接口觸發(fā)的信息,需要開(kāi)啟10個(gè)線程,那么就可以創(chuàng)建10個(gè)線程去執(zhí)行它的私有業(yè)務(wù),然后再額外創(chuàng)建一個(gè)線程去拿到前面那10個(gè)線程的執(zhí)行返回結(jié)果并進(jìn)行公共業(yè)務(wù)的處理。

這樣有個(gè)好處,就是能讓線程池很快的回收線程,能有效防止線程的阻塞

量化:

單個(gè)私有業(yè)務(wù)1秒鐘能執(zhí)行完成,單個(gè)公共業(yè)務(wù)需要5秒鐘才能執(zhí)行完成,如果接口被觸發(fā),發(fā)現(xiàn)需要?jiǎng)?chuàng)建100個(gè)線程執(zhí)行,那么線程池回收這些線程池至少需要等待6秒,如果按照前面說(shuō)的分成兩個(gè)線程,那么就需要?jiǎng)?chuàng)建101個(gè)線程,而1秒后就能回收掉執(zhí)行完成的100個(gè)線程

但是這里需要做權(quán)衡,如果接口被觸發(fā)的時(shí)候發(fā)現(xiàn)需要開(kāi)啟的線程比較多且公共業(yè)務(wù)很耗時(shí),這種情況下執(zhí)行公共業(yè)務(wù)只有單個(gè)線程同步執(zhí)行,那么這個(gè)線程就會(huì)執(zhí)行比較長(zhǎng)的時(shí)間,所以執(zhí)行公共業(yè)務(wù)的時(shí)候也可根據(jù)實(shí)際情況開(kāi)啟多個(gè)線程。

下面寫(xiě)了個(gè)小demo:

1.私有業(yè)務(wù)的類(lèi):

@Component
public class Calculation {
  public Result cal(String req, int a, int b) {
    System.out.println("請(qǐng)求id:" + req + "  結(jié)果:" + (a + b));
    return new Result(req, a + b);
  }
}

2.公共業(yè)務(wù)的類(lèi):

@Component
public class SomethingElse {
  public void doElse(Result result) {
    try {
      System.out.println(Thread.currentThread().getName() + " : 開(kāi)始做其他事情,請(qǐng)求號(hào):" + result.getReq() + " ,請(qǐng)求結(jié)果:" + result.getSum());
      Thread.sleep(2000);
      System.out.println(Thread.currentThread().getName() + " : 完成做其他事情,請(qǐng)求號(hào):" + result.getReq() + " ,請(qǐng)求結(jié)果:" + result.getSum());
    } catch (InterruptedException e) {
    }
  }
}

3.私有業(yè)務(wù)的線程類(lèi):

public class CallTask implements Callable<Result> {
  private String req;
  private int a;
  private int b;
  @Override
  public Result call() throws Exception {
    Calculation calculation = Main.applicationContext.getBean(Calculation.class);
    return calculation.cal(req, a, b);
  }
  public CallTask(String req, int a, int b) {
    this.req = req;
    this.a = a;
    this.b = b;
  }
  // getter and setter 等等
}

4.公共業(yè)務(wù)的線程類(lèi):

public class ElseTask implements Runnable {
  private CompletionService<Result> cs;
  private int threadCount;
  public ElseTask(CompletionService<Result> cs, int threadCount) {
    this.cs = cs;
    this.threadCount = threadCount;
  }
  @Override
  public void run() {
    SomethingElse somethingElse = Main.applicationContext.getBean(SomethingElse.class);
    doElse(somethingElse);
  }
  private void doElse(SomethingElse somethingElse) {
    try {
      for (int i = 0; i < threadCount; i++) {
        Future<Result> take = cs.take();
        Result result = take.get();
        somethingElse.doElse(result);
      }
    } catch (Exception e) {
    }
  }
  // getter and setter 等等
}

6.測(cè)試主方法:

@Service
public class Main implements ApplicationContextAware {
  public static ApplicationContext applicationContext = null;
  public static void main(String[] args) throws InterruptedException {
    AbstractApplicationContext appContext = new ClassPathXmlApplicationContext("application01.xml");
    ExecutorService executorService = Executors.newFixedThreadPool(100);
    CompletionService<Result> cs = new ExecutorCompletionService(executorService);
    //這里啟動(dòng)執(zhí)行計(jì)算的線程
    cs.submit(new CallTask("req001", 0, 1));
    cs.submit(new CallTask("req002", 0, 2));
    cs.submit(new CallTask("req003", 0, 3));
    cs.submit(new CallTask("req004", 0, 4));
    cs.submit(new CallTask("req005", 0, 5));
    //專(zhuān)門(mén)的監(jiān)控線程,并執(zhí)行其他耗時(shí)的線程
    executorService.execute(new ElseTask(cs, 5));
    executorService.shutdown();
    appContext.registerShutdownHook();
  }
  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }
}

執(zhí)行結(jié)果如下:

核心思想: 將多線程的公有的業(yè)務(wù)抽出來(lái)(前提是公有業(yè)務(wù)比較耗時(shí),不然就沒(méi)必要了)在其他線程里面執(zhí)行。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教。

相關(guān)文章

  • SpringBoot?SPI?機(jī)制和實(shí)現(xiàn)自定義?starter

    SpringBoot?SPI?機(jī)制和實(shí)現(xiàn)自定義?starter

    這篇文章主要介紹了SpringBoot?SPI機(jī)制和實(shí)現(xiàn)自定義?starter,全稱(chēng)是Service?Provider?Interface。簡(jiǎn)單翻譯的話(huà),就是服務(wù)提供者接口,是一種尋找服務(wù)實(shí)現(xiàn)的機(jī)制
    2022-08-08
  • Java中的異常處理之try-catch使用詳解

    Java中的異常處理之try-catch使用詳解

    這篇文章主要介紹了Java中的異常處理之try-catch使用的相關(guān)資料,包括異常的概念、try-catch語(yǔ)句的基本結(jié)構(gòu)、使用示例、多個(gè)catch塊的使用、try-catch-finally的執(zhí)行順序、try-with-resources語(yǔ)句以及總結(jié),需要的朋友可以參考下
    2024-12-12
  • 使用Spring AntPathMatcher的doMatch方法

    使用Spring AntPathMatcher的doMatch方法

    這篇文章主要介紹了使用Spring AntPathMatcher的doMatch方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • 搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目

    搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目

    本文主要介紹了搭建簡(jiǎn)單的Spring-Data JPA項(xiàng)目,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • JVM調(diào)優(yōu)OutOfMemoryError異常分析

    JVM調(diào)優(yōu)OutOfMemoryError異常分析

    這篇文章主要為大家介紹了JVM調(diào)優(yōu)OutOfMemoryError異常分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • SpringBoot3讀取配置文件application.properties屬性值的幾種方式

    SpringBoot3讀取配置文件application.properties屬性值的幾種方式

    這篇文章主要介紹了SpringBoot3讀取配置文件application.properties屬性值的幾種方式,文中通過(guò)代碼示例給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-11-11
  • Java 定時(shí)器的使用示例

    Java 定時(shí)器的使用示例

    這篇文章主要介紹了Java 定時(shí)器的使用,幫助大家更好的理解和使用Java time類(lèi),感興趣的朋友可以了解下
    2020-09-09
  • SpringBoot項(xiàng)目啟動(dòng)時(shí)初始化操作常見(jiàn)的幾種方式

    SpringBoot項(xiàng)目啟動(dòng)時(shí)初始化操作常見(jiàn)的幾種方式

    這篇文章主要介紹了SpringBoot項(xiàng)目啟動(dòng)時(shí)初始化操作常見(jiàn)的幾種方式,這些方法可以幫助開(kāi)發(fā)者在服務(wù)啟動(dòng)時(shí)自動(dòng)執(zhí)行必要的初始化操作,需要的朋友可以參考下
    2025-02-02
  • Spring Boot中優(yōu)雅的獲取yml文件工具類(lèi)

    Spring Boot中優(yōu)雅的獲取yml文件工具類(lèi)

    今天小編就為大家分享一篇關(guān)于Spring Boot中優(yōu)雅的獲取yml文件工具類(lèi),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • java實(shí)現(xiàn)建造者模式(Builder Pattern)

    java實(shí)現(xiàn)建造者模式(Builder Pattern)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)建造者模式Builder Pattern,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10

最新評(píng)論

勃利县| 滦平县| 历史| 微博| 都兰县| 慈利县| 黔西县| 钟山县| 南投县| 湘西| 内丘县| 沂源县| 延长县| 宁陕县| 尤溪县| 陇西县| 北辰区| 同心县| 宾川县| 白河县| 石阡县| 河南省| 镇江市| 武强县| 碌曲县| 巫溪县| 綦江县| 中方县| 肇州县| 靖远县| 英吉沙县| 富民县| 祥云县| 阳信县| 双鸭山市| 吉林省| 吴旗县| 沈丘县| 荃湾区| 淄博市| 漾濞|