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

Java并發(fā)中線程封閉知識(shí)點(diǎn)詳解

 更新時(shí)間:2019年07月16日 11:37:46   作者:鍋外的大佬  
在本篇文章里我們給大家整理了關(guān)于Java并發(fā)中線程封閉的知識(shí)點(diǎn)總結(jié)內(nèi)容,需要的朋友們學(xué)習(xí)參考下。

在這篇文章中,我們將探討線程封閉是什么意思,以及我們?nèi)绾螌?shí)現(xiàn)它。 所以,讓我們直接開始吧。

線程封閉基礎(chǔ)知識(shí)點(diǎn)

實(shí)現(xiàn)好的并發(fā)是一件困難的事情,所以很多時(shí)候我們都想躲避并發(fā)。避免并發(fā)最簡(jiǎn)單的方法就是線程封閉。什么是線程封閉呢?

就是把對(duì)象封裝到一個(gè)線程里,只有這一個(gè)線程能看到此對(duì)象。那么這個(gè)對(duì)象就算不是線程安全的也不會(huì)出現(xiàn)任何安全問題。實(shí)現(xiàn)線程封閉有哪些方法呢?

1:ad-hoc線程封閉

這是完全靠實(shí)現(xiàn)者控制的線程封閉,他的線程封閉完全靠實(shí)現(xiàn)者實(shí)現(xiàn)。也是最糟糕的一種線程封閉。所以我們直接把他忽略掉吧。

2:棧封閉

棧封閉是我們編程當(dāng)中遇到的最多的線程封閉。什么是棧封閉呢?簡(jiǎn)單的說就是局部變量。多個(gè)線程訪問一個(gè)方法,此方法中的
局部變量都會(huì)被拷貝一分兒到線程棧中。所以局部變量是不被多個(gè)線程所共享的,也就不會(huì)出現(xiàn)并發(fā)問題。所以能用局部變量就別用全局的變量,全局變量容易引起并發(fā)問題。

3:ThreadLocal封閉

使用ThreadLocal是實(shí)現(xiàn)線程封閉的最好方法,有興趣的朋友可以研究一下ThreadLocal的源碼,其實(shí)ThreadLocal內(nèi)部維護(hù)了一個(gè)Map,Map的key是每個(gè)線程的名稱,而Map的值就是我們要封閉的對(duì)象。每個(gè)線程中的對(duì)象都對(duì)應(yīng)著Map中一個(gè)值,也就是ThreadLocal利用Map實(shí)現(xiàn)了對(duì)象的線程封閉。這里就不說ThreadLocal的使用方法了,度娘一下便知。

1. 線程封閉

大多數(shù)的并發(fā)問題僅發(fā)生在我們想要在線程之間共享可變變量或可變狀態(tài)時(shí)。如果在多個(gè)線程之間操作共享變量,則所有線程都將能夠讀取和修改變量的值,從而出現(xiàn)意外或不正確的結(jié)果。一種簡(jiǎn)單的避免此問題的方式是不在線程之間共享數(shù)據(jù)。 這種技術(shù)稱為線程封閉,是在我們的應(yīng)用程序中實(shí)現(xiàn)線程安全的最簡(jiǎn)單方法之一。

Java 語言本身沒有任何強(qiáng)制執(zhí)行線程封閉的方法。線程封閉是通過不允許多個(gè)線程同時(shí)使用同一個(gè)狀態(tài)的方式的程序設(shè)計(jì)來實(shí)現(xiàn)的,因此由程序?qū)崿F(xiàn)強(qiáng)制執(zhí)行。 幾種類型的線程封閉,如下所示:

1.1 Ad-Hoc 線程封閉

Ad-hoc 線程封閉描述了線程封閉的方式,由開發(fā)人員或從事該項(xiàng)目的開發(fā)人員確保僅在單個(gè)線程內(nèi)使用此對(duì)象。 這種方式方法可用性不高,在大多數(shù)情況下應(yīng)該避免。

Ad-hoc 線程封閉下的一個(gè)特例適用于 volatile 變量。 只要確保 volatile 變量?jī)H從單個(gè)線程寫入,就可以安全地對(duì)共享 volatile 變量執(zhí)讀 - 改 - 寫操作。在這種情況下,您將修改限制在單個(gè)線程以防止競(jìng)爭(zhēng)條件,并且 volatile 變量的可見性保證確保其他線程看到最新值。

1.2 棧封閉

棧封閉將變量或?qū)ο蠓忾]在線程的棧中。這比 Ad-hoc 線程封閉強(qiáng)得多,因?yàn)樗ㄟ^定義堆棧本身中的變量狀態(tài)來進(jìn)一步限制對(duì)象的范圍。例如,請(qǐng)考慮以下代碼:

private long numberOfPeopleNamedJohn(List<Person> people) {
 List<Person> localPeople = new ArrayList<>();
 localPeople.addAll(people);
 return localPeople.stream().filter(person -> person.getFirstName().equals("John")).count();
}

在上面的代碼中,我們傳遞一個(gè) person 對(duì)象的 list 但不直接使用它。 相反,我們創(chuàng)建自己的 list,該 list 是當(dāng)前正在執(zhí)行的線程的本地 list,并將變量 people中的所有 person 添加到 localPeople。由于我們僅在 numberOfPeopleNamedJohn方法中定義列表,這使得變量localPeople 受到堆棧隔離保護(hù),因?yàn)樗淮嬖谟谝粋€(gè)線程的堆棧上,因此任何其他線程都無法訪問它。這使得 localPeople 線程安全。 唯一需要注意的是,不應(yīng)該讓 localPeople 的作用于超過這個(gè)方法的范圍,以保證堆棧的隔離控制。在定義這個(gè)變量時(shí),應(yīng)該記錄或注釋為什么要定義這個(gè)變量,通常,只有在當(dāng)前開發(fā)人員的腦海中才不讓它超出方法的作用域,但是在將來,另一個(gè)開發(fā)人員可能會(huì)不知道為何如此設(shè)計(jì)而陷入困境。

1.3 ThreadLocal

ThreadLocal允許我們將每個(gè)線程 ID 與相應(yīng)對(duì)象的值相關(guān)聯(lián)。 它允許我們?yōu)椴煌木€程存儲(chǔ)不同的對(duì)象,并維護(hù)哪個(gè)對(duì)象對(duì)應(yīng)于哪個(gè)線程。它有 set 和 get 方法,這些方法為使用它的每個(gè)線程維護(hù)一個(gè)單獨(dú)的 value 副本。get() 方法總是返回從當(dāng)前正在執(zhí)行的線程傳遞給 set()的最新值。 我們來看一個(gè)例子:

public class ThreadConfinementUsingThreadLocal {
  public static void main(String[] args) {
    ThreadLocal<String> stringHolder = new ThreadLocal<>();
    Runnable runnable1 = () -> {
      stringHolder.set("Thread in runnable1");
      try {
        Thread.sleep(5000);
        System.out.println(stringHolder.get());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    };
    Runnable runnable2 = () -> {
      stringHolder.set("Thread in runnable2");
      try {
        Thread.sleep(2000);
        stringHolder.set("string in runnable2 changed");
        Thread.sleep(2000);
        System.out.println(stringHolder.get());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    };
    Runnable runnable3 = () -> {
      stringHolder.set("Thread in runnable3");
      try {
        Thread.sleep(5000);
        System.out.println(stringHolder.get());
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    };
    Thread thread1 = new Thread(runnable1);
    Thread thread2 = new Thread(runnable2);
    Thread thread3 = new Thread(runnable3);
    thread1.start();
    thread2.start();
    thread3.start();
  }
}

在上面的例子中,我們使用相同的 ThreadLocal 對(duì)象 stringHolder 執(zhí)行了三個(gè)線程。正如你在這里看到的,我們首先在 stringHolder 對(duì)象的每個(gè)線程中設(shè)置一個(gè)字符串,使其包含三個(gè)字符串。然后,經(jīng)過一些暫停后,我們只更改了第二個(gè)線程的值。 以下是該程序的輸出:

string in runnable2 changed
Thread in runnable1
Thread in runnable3

正如您在上面的輸出中所看到的,線程2的字符串已更改,但線程1和線程3的字符串未受影響。如果我們?cè)趶?ThreadLocal 獲取特定線程的值之前沒有設(shè)置任何值,那么它返回null。 線程終止后,“ThreadLocal” 中特定于線程的對(duì)象就可以進(jìn)行垃圾回收了。

相關(guān)文章

  • java將數(shù)字價(jià)格轉(zhuǎn)換為中文大寫代碼示例(工具類)

    java將數(shù)字價(jià)格轉(zhuǎn)換為中文大寫代碼示例(工具類)

    這篇文章主要介紹了java將數(shù)字價(jià)格轉(zhuǎn)換為中文大寫的相關(guān)資料,在Java中實(shí)現(xiàn)將數(shù)字價(jià)格轉(zhuǎn)換為中文大寫需要將數(shù)字分解為各個(gè)部分(如個(gè)位、十位、百位等),并根據(jù)這些部分轉(zhuǎn)換為對(duì)應(yīng)的中文大寫數(shù)字,需要的朋友可以參考下
    2024-10-10
  • Spring整合MyBatis圖示過程解析

    Spring整合MyBatis圖示過程解析

    這篇文章主要介紹了Spring整合MyBatis圖示過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • 最值得Java開發(fā)者收藏的網(wǎng)站

    最值得Java開發(fā)者收藏的網(wǎng)站

    這篇文章主要為大家分享了最值得Java開發(fā)者收藏的11個(gè)網(wǎng)站,幫助Java開發(fā)者提升編程能力
    2016-11-11
  • Java如何通過反射獲取Constructor、Field、Method對(duì)象

    Java如何通過反射獲取Constructor、Field、Method對(duì)象

    反射指的是對(duì)象的反向處理操作,根據(jù)對(duì)象取得對(duì)象的來源信息,在反射的世界里面,看重的不再是一個(gè)對(duì)象,而是對(duì)象身后的組成,下面這篇文章主要給大家介紹了關(guān)于Java如何通過反射獲取Constructor、Field、Method對(duì)象的相關(guān)資料,需要的朋友可以參考下
    2022-06-06
  • maven項(xiàng)目打jar包并包含所有依賴詳細(xì)教程

    maven項(xiàng)目打jar包并包含所有依賴詳細(xì)教程

    maven打包生成的普通jar包,只包含該工程下源碼編譯結(jié)果,不包含依賴內(nèi)容,下面這篇文章主要給大家介紹了關(guān)于maven項(xiàng)目打jar包并包含所有依賴的相關(guān)資料,需要的朋友可以參考下
    2023-05-05
  • java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)分析

    java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)分析

    這篇文章主要介紹了java虛擬機(jī)運(yùn)行時(shí)數(shù)據(jù)區(qū)分析,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • SpringMVC后端返回?cái)?shù)據(jù)到前端代碼示例

    SpringMVC后端返回?cái)?shù)據(jù)到前端代碼示例

    這篇文章主要介紹了SpringMVC后端返回?cái)?shù)據(jù)到前端代碼示例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • Java的云打印Lodop

    Java的云打印Lodop

    這篇文章主要介紹了Java的云打印Lodop 的相關(guān)資料,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-07-07
  • java的異常與處理機(jī)制分析【附面試題】

    java的異常與處理機(jī)制分析【附面試題】

    這篇文章主要介紹了java的異常與處理機(jī)制,結(jié)合實(shí)例形式分析了Java異常與處理機(jī)制的概念、原理、相關(guān)操作技巧與注意事項(xiàng),并附帶面試題分析供大家參考,需要的朋友可以參考下
    2019-05-05
  • MyBatis-Plus介紹及Spring Boot 3集成指南

    MyBatis-Plus介紹及Spring Boot 3集成指南

    本文介紹了MyBatis-Plus的基本特性及其與Spring Boot 3的集成步驟,通過使用MyBatis-Plus,開發(fā)者可以快速地搭建和開發(fā)數(shù)據(jù)訪問層,同時(shí)提高代碼質(zhì)量和開發(fā)效率,感興趣的朋友一起看看吧
    2024-05-05

最新評(píng)論

商城县| 象山县| 武隆县| 凤凰县| 兴安盟| 太仆寺旗| 湘潭市| 封丘县| 清流县| 宜兴市| 安福县| 永春县| 浦城县| 岗巴县| 龙川县| 厦门市| 翼城县| 迁安市| 安多县| 古浪县| 乡城县| 宁德市| 红桥区| 西昌市| 苏州市| 津南区| 洪雅县| 沈阳市| 旺苍县| 库伦旗| 花垣县| 肃宁县| 民乐县| 鸡东县| 新晃| 金平| 托里县| 磐安县| 兴业县| 金寨县| 大渡口区|