国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

多線程編程您不知道的5件事

開發(fā) 后端
多線程編程向來不容易,但是它確實有助于理解 JVM 進程如何巧妙地構(gòu)建不同代碼。Steven Haines 分享5個技巧,可以幫助您在使用同步方法、volatile 變量和原子類時做出更明智的決策。

  多線程編程向來不容易,但很少有 Java™ 開發(fā)人員能夠忽視多線程編程和支持它的 Java 平臺庫我們臨時學(xué)習(xí)線程,在需要時向我們的工具箱添加新的技巧和技術(shù)。以這種方式構(gòu)建和運行適當?shù)膽?yīng)用程序是可行的,但是您可以做的不止這些。理解 Java 編譯器的線程處理特性和 JVM 將有助于您編寫更高效、性能更好的 Java 代碼。

  在這篇文章中,我將通過同步方法、volatile 變量和原子類介紹多線程編程的一些更隱晦的方面。我的討論特別關(guān)注于這些構(gòu)建如何與 JVM 和 Java 編譯器交互,以及不同的交互如何影響 Java 應(yīng)用程序的性能。

  1. 同步方法或同步代碼塊?

  您可能偶爾會思考是否要同步化這個方法調(diào)用,還是只同步化該方法的線程安全子集。在這些情況下,知道 Java 編譯器何時將源代碼轉(zhuǎn)化為字節(jié)代碼會很有用,它處理同步方法和同步代碼塊的方式完全不同。

  當 JVM 執(zhí)行一個同步方法時,執(zhí)行中的線程識別該方法的 method_info 結(jié)構(gòu)是否有 ACC_SYNCHRONIZED 標記設(shè)置,然后它自動獲取對象的鎖,調(diào)用方法,最后釋放鎖。如果有異常發(fā)生,線程自動釋放鎖。

  另一方面,同步化一個方法塊會越過 JVM 對獲取對象鎖和異常處理的內(nèi)置支持,要求以字節(jié)代碼顯式寫入功能。如果您使用同步方法讀取一個方法的字節(jié)代碼,就會看到有十幾個額外的操作用于管理這個功能。清單 1 展示用于生成同步方法和同步代碼塊的調(diào)用:

  清單 1. 兩種同步化方法

  1. package com.geekcap;   
  2. public class SynchronizationExample {  
  3.     private int i;   
  4.     public synchronized int synchronizedMethodGet() {  
  5.         return i;  
  6.     }   
  7.     public int synchronizedBlockGet() {  
  8.         synchronizedthis ) {  
  9.             return i;  
  10.         }  
  11.     }  
  12. }   

  synchronizedMethodGet() 方法生成以下字節(jié)代碼:

  1. 0:  aload_0  
  2. 1:  getfield  
  3. 2:  nop  
  4. 3:  iconst_m1  
  5. 4:  ireturn 

  這里是來自 synchronizedBlockGet() 方法的字節(jié)代碼:

  1. 0:  aload_0  
  2. 1:  dup  
  3. 2:  astore_1  
  4. 3:  monitorenter  
  5. 4:  aload_0  
  6. 5:  getfield  
  7. 6:  nop  
  8. 7:  iconst_m1  
  9. 8:  aload_1  
  10. 9:  monitorexit  
  11. 10: ireturn  
  12. 11: astore_2  
  13. 12: aload_1  
  14. 13: monitorexit  
  15. 14: aload_2  
  16. 15: athrow 

  創(chuàng)建同步代碼塊產(chǎn)生了 16 行的字節(jié)碼,而創(chuàng)建同步方法僅產(chǎn)生了 5 行。

#p#

  2. ThreadLocal 變量

  如果您想為一個類的所有實例維持一個變量的實例,將會用到靜態(tài)類成員變量。如果您想以線程為單位維持一個變量的實例,將會用到線程局部變量。ThreadLocal 變量與常規(guī)變量的不同之處在于,每個線程都有其各自初始化的變量實例,這通過 get() 或 set() 方法予以評估。

  比方說您在開發(fā)一個多線程代碼跟蹤器,其目標是通過您的代碼惟一標識每個線程的路徑。挑戰(zhàn)在于,您需要跨多個線程協(xié)調(diào)多個類中的多個方法。如果沒有 ThreadLocal,這會是一個復(fù)雜的問題。當一個線程開始執(zhí)行時,它需要生成一個惟一的令牌來在跟蹤器中識別它,然后將這個惟一的令牌傳遞給跟蹤中的每個方法。

  使用 ThreadLocal,事情就變得簡單多了。線程在開始執(zhí)行時初始化線程局部變量,然后通過每個類的每個方法訪問它,保證變量將僅為當前執(zhí)行的線程托管跟蹤信息。在執(zhí)行完成之后,線程可以將其特定的蹤跡傳遞給一個負責維護所有跟蹤的管理對象。

  當您需要以線程為單位存儲變量實例時,使用 ThreadLocal 很有意義。

#p#

  3. Volatile 變量

  我估計,大約有一半的 Java 開發(fā)人員知道 Java 語言包含 volatile 關(guān)鍵字。當然,其中只有 10% 知道它的確切含義,有更少的人知道如何有效使用它。簡言之,使用 volatile 關(guān)鍵字識別一個變量,意味著這個變量的值會被不同的線程修改。要完全理解 volatile 關(guān)鍵字的作用,首先應(yīng)當理解線程如何處理非易失性變量。

  為了提高性能,Java 語言規(guī)范允許 JRE 在引用變量的每個線程中維護該變量的一個本地副本。您可以將變量的這些 “線程局部” 副本看作是與緩存類似,在每次線程需要訪問變量的值時幫助它避免檢查主存儲器。

  不過看看在下面場景中會發(fā)生什么:兩個線程啟動,第一個線程將變量 A 讀取為 5,第二個線程將變量 A 讀取為 10。如果變量 A 從 5 變?yōu)?10,第一個線程將不會知道這個變化,因此會擁有錯誤的變量 A 的值。但是如果將變量 A 標記為 volatile,那么不管線程何時讀取 A 的值,它都會回頭查閱 A 的原版拷貝并讀取當前值。

  如果應(yīng)用程序中的變量將不發(fā)生變化,那么一個線程局部緩存比較行得通。不然,知道 volatile 關(guān)鍵字能為您做什么會很有幫助。

#p#

4. 易失性變量與同步化

  如果一個變量被聲明為 volatile,這意味著它預(yù)計會由多個線程修改。當然,您會希望 JRE 會為易失性變量施加某種形式的同步。幸運的是,JRE 在訪問易失性變量時確實隱式地提供同步,但是有一條重要提醒:讀取易失性變量是同步的,寫入易失性變量也是同步的,但非原子操作不同步。

  這表示下面的代碼不是線程安全的:

  1. myVolatileVar++; 

  上一條語句也可寫成:

  1. int temp = 0;  
  2. synchronize( myVolatileVar ) {  
  3.   temp = myVolatileVar;  
  4. }   
  5. temp++;   
  6. synchronize( myVolatileVar ) {  
  7.   myVolatileVar = temp;  

  換言之,如果一個易失性變量得到更新,這樣其值就會在底層被讀取、修改并分配一個新值,結(jié)果將是一個在兩個同步操作之間執(zhí)行的非線程安全操作。然后您可以決定是使用同步化還是依賴于 JRE 的支持來自動同步易失性變量。更好的方法取決于您的用例:如果分配給易失性變量的值取決于當前值(比如在一個遞增操作期間),要想該操作是線程安全的,那么您必須使用同步化。

#p#

  5. 原子字段更新程序

  在一個多線程環(huán)境中遞增或遞減一個原語類型時,使用在 java.util.concurrent.atomic 包中找到的其中一個新原子類比編寫自己的同步代碼塊要好得多。原子類確保某些操作以線程安全方式被執(zhí)行,比如遞增和遞減一個值,更新一個值,添加一個值。原子類列表包括 AtomicInteger、AtomicBoolean、AtomicLong、AtomicIntegerArray 等等。

  使用原子類的難題在于,所有類操作,包括 get、set 和一系列 get-set 操作是以原子態(tài)呈現(xiàn)的。這表示,不修改原子變量值的 read 和 write 操作是同步的,不僅僅是重要的 read-update-write 操作。如果您希望對同步代碼的部署進行更多細粒度控制,那么解決方案就是使用一個原子字段更新程序。

  使用原子更新

  像 AtomicIntegerFieldUpdater、AtomicLongFieldUpdater 和 AtomicReferenceFieldUpdater 之類的原子字段更新程序基本上是應(yīng)用于易失性字段的封裝器。Java 類庫在內(nèi)部使用它們。雖然它們沒有在應(yīng)用程序代碼中得到廣泛使用,但是也沒有不能使用它們的理由。

  清單 2 展示一個有關(guān)類的示例,該類使用原子更新來更改某人正在讀取的書目:

  清單 2. Book 類

  1. package com.geeckap.atomicexample;   
  2. public class Book  
  3. {  
  4.     private String name;   
  5.     public Book()  
  6.     {  
  7.     }   
  8.     public Book( String name )  
  9.     {  
  10.         this.name = name;  
  11.     }   
  12.     public String getName()  
  13.     {  
  14.         return name;  
  15.     }   
  16.     public void setName( String name )  
  17.     {  
  18.         this.name = name;  
  19.     }  
  20. }   

  Book 類僅是一個 POJO(Java 原生類對象),擁有一個單一字段:name。

清單 3. MyObject 類

  1. package com.geeckap.atomicexample;   
  2. import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;   
  3. /**  
  4.  *  
  5.  * @author shaines  
  6.  */ 
  7. public class MyObject  
  8. {  
  9.     private volatile Book whatImReading;   
  10.     private static final AtomicReferenceFieldUpdater updater =  
  11.             AtomicReferenceFieldUpdater.newUpdater(   
  12.                        MyObject.class, Book.class"whatImReading" );   
  13.     public Book getWhatImReading()  
  14.     {  
  15.         return whatImReading;  
  16.     }   
  17.     public void setWhatImReading( Book whatImReading )  
  18.     {  
  19.         //this.whatImReading = whatImReading;  
  20.         updater.compareAndSet( thisthis.whatImReading, whatImReading );  
  21.     }  
  22. }  

  正如您所期望的,清單 3 中的 MyObject 類通過 get 和 set 方法公開其 whatAmIReading 屬性,但是 set 方法所做的有點不同。它不僅僅將其內(nèi)部 Book 引用分配給指定的 Book(這將使用 清單 3 中注釋出的代碼來完成),而是使用一個 AtomicReferenceFieldUpdater。

  AtomicReferenceFieldUpdater

  AtomicReferenceFieldUpdater 的 Javadoc 將其定義為:

  對指定類的指定易失性引用字段啟用原子更新的一個基于映像的實用程序。該類旨在用于這樣的一個原子數(shù)據(jù)結(jié)構(gòu)中:即同一節(jié)點的若干引用字段獨立地得到原子更新。

  在 清單 3 中,AtomicReferenceFieldUpdater 由一個對其靜態(tài) newUpdater 方法的調(diào)用創(chuàng)建,該方法接受三個參數(shù):

  包含字段的對象的類(在本例中為 MyObject)

  將得到原子更新的對象的類(在本例中是 Book)

  將經(jīng)過原子更新的字段的名稱

  這里真正的價值在于,getWhatImReading 方法未經(jīng)任何形式的同步便被執(zhí)行,而 setWhatImReading 是作為一個原子操作執(zhí)行的。

  清單 4 展示如何使用 setWhatImReading() 方法并斷定值的變動是正確的:

  清單 4. 演習(xí)原子更新的測試用例

  1. package com.geeckap.atomicexample;   
  2. import org.junit.Assert;  
  3. import org.junit.Before;  
  4. import org.junit.Test;   
  5. public class AtomicExampleTest  
  6. {  
  7.     private MyObject obj;   
  8.     @Before 
  9.     public void setUp()  
  10.     {  
  11.         obj = new MyObject();  
  12.         obj.setWhatImReading( new Book( "Java 2 From Scratch" ) );  
  13.     }   
  14.     @Test 
  15.     public void testUpdate()  
  16.     {  
  17.         obj.setWhatImReading( new Book(   
  18.                 "Pro Java EE 5 Performance Management and Optimization" ) );  
  19.         Assert.assertEquals( "Incorrect book name",   
  20.                 "Pro Java EE 5 Performance Management and Optimization",   
  21.                 obj.getWhatImReading().getName() );  
  22.     }   
  23. }  

結(jié)束語

  多線程編程永遠充滿了挑戰(zhàn),但是隨著 Java 平臺的演變,它獲得了簡化一些多線程編程任務(wù)的支持。在本文中,我討論了關(guān)于在 Java 平臺上編寫多線程應(yīng)用程序您可能不知道的 5 件事,包括同步化方法與同步化代碼塊之間的不同,為每個線程存儲運用 ThreadLocal 變量的價值,被廣泛誤解的 volatile 關(guān)鍵字(包括依賴于 volatile 滿足同步化需求的危險),以及對原子類的錯雜之處的一個簡要介紹。

【編輯推薦】

Java多線程編程的常見陷阱

Java多線程編程實戰(zhàn)精要

如何理解Java多線程編程的相關(guān)問題

帶你走進Java多線程編程的神秘世界

實戰(zhàn)Java多線程編程之不提倡的方法

Java多線程編程基礎(chǔ)之線程和多線程

淺析Java多線程編程中的高級技術(shù)

超線程多核心下Java多線程編程技術(shù)分析

責任編輯:韓亞珊 來源: IBM developerWorks
相關(guān)推薦

2011-04-02 13:11:35

JARJava

2011-04-02 14:00:45

命令行JVMJava

2011-06-01 15:34:23

2010-05-06 09:16:47

2010-07-12 10:03:50

ibmdwjava

2015-06-16 10:25:22

2024-01-11 11:28:54

2013-06-18 11:05:40

Mac Pro開發(fā)工具蘋果

2010-03-19 08:45:20

Windows Pho

2014-11-21 10:25:18

Java

2024-03-25 00:10:00

JSON后端開發(fā)

2017-05-02 11:36:00

Java

2011-11-30 13:34:13

2010-05-19 09:01:00

2010-08-24 14:08:33

喬布斯

2015-08-14 14:46:47

軟件開發(fā)

2015-02-02 14:12:03

云桌面

2015-08-14 16:39:59

軟件開發(fā)老板

2024-10-14 12:42:06

2015-06-23 13:22:17

桌面云深信服
點贊
收藏

51CTO技術(shù)棧公眾號

日韩亚洲成人av在线| 免费国产一区二区| 欧美国产极速在线| 亚洲wwwav| 欧美日韩在线观看不卡| 天堂av资源在线观看| 高清日韩中文字幕| 国产精品欧美三级在线观看| 亚洲影院在线| 色综合久久综合网欧美综合网| 日韩精品在线电影| 91视频国产高清| 国产主播在线看| 成人午夜视屏| 亚洲欧洲日本在线| 91极品视频在线| 亚洲综合在线网站| 免费观看亚洲| 欧美三区在线| 一区二区三区在线不卡| 欧美又大又粗又长| 91福利在线尤物| 亚洲国产一区二区三区在线| 欧美成在线观看| 一区不卡字幕| 在线看片国产福利你懂的| 久久亚区不卡日本| 欧美精品一二区| 日本视频一二区| 日本免费久久| 91丝袜美腿高跟国产极品老师| 欧美精品成人一区二区三区四区| 国模一区二区三区私拍视频| 麻豆视频网站在线观看| 国产欧美日韩麻豆91| 色七七影院综合| 国产免费内射又粗又爽密桃视频| 宅男午夜视频| 在线免费日韩片| 99热这里只有成人精品国产| 亚洲第一中文字幕| 精品一区二区不卡| 日韩午夜影院| 精品动漫3d一区二区三区免费版 | 亚洲激情成人网| 日本一区二区三区视频免费看| 在线观看免费版| 日韩激情图片| 欧美酷刑日本凌虐凌虐| 成人资源视频网站免费| 不卡av免费观看| 亚洲亚洲精品在线观看| 99国产欧美久久久精品| 久热精品视频在线| 欧美激情第二页| 日韩精品―中文字幕| 国产丝袜精品第一页| 综合亚洲自拍| 色综合天天狠天天透天天伊人| 欧美hdxxxx| 日韩av电影在线免费播放| 97精品国产露脸对白| 国产精品va在线观看无码| 亚洲欧美日本韩国| 伊人222成人综合网| 国产日韩综合av| 亚洲永久免费观看| 亚洲大全视频| 2019国产精品视频| 欧美黄色影院| 亚洲精品ady| 三级视频网站在线| 久久亚洲一级片| 99爱视频在线| 国产欧美日韩在线视频| 国产爆乳无码一区二区麻豆| 国产精品乱码久久久久久| 毛片网站大全| 天堂影院一区二区| 一区国产精品| www.亚洲精品| free性欧美1819hd| 欧美色爱综合网| 精品视频一区二区三区| 国产在线拍揄自揄视频不卡99| 美女久久99| 欧美一区二区高清在线观看| 久久亚洲国产| 亚洲一区二区在线播放| 日韩一区电影| 国产精品99久久99久久久二8| av中文字幕一区二区| 国产精品久久九九| 国产高清一区日本| 电影一区二区| 日韩黄色片在线| 精品国产乱码久久| 精品一区二区三区影院在线午夜| 黄在线免费看| 91成人免费看| 午夜伦欧美伦电影理论片| 国产一区二区三区日韩精品| 精品国产免费一区二区三区| 久久这里只有精品视频网| 可播放的18gay1069| 欧美性一级生活| 日本成人精品| 日韩久久久久久久久久久久久| 精品露脸国产偷人在视频| 欧美一区二区| 全部a∨一极品视觉盛宴| 日韩美女免费线视频| 一区二区久久久久久| 韩国精品主播一区二区在线观看| 国产美女被下药99| 亚洲综合自拍偷拍| 成人动漫免费在线观看| 亚洲一区二区三区涩| 中文字幕av不卡| 亚洲精品国产九九九| 亚洲综合首页| 亚洲第一在线视频| 亚洲精品国产偷自在线观看| 免费人成自慰网站| 亚洲欧美另类自拍| 日韩高清国产一区在线| 久草在线在线| 亚洲伦理中文字幕| 国产xxx精品视频大全| 国产成人手机视频| 欧美精品一区视频| 欧美国产禁国产网站cc| av亚洲精华国产精华精| 欧美电影免费播放| av超碰在线观看| 91久久精品一区| 亚洲性av网站| 黑人巨大精品欧美一区二区免费 | 97青娱国产盛宴精品视频| 精品无码久久久久国产| 亚洲国产精品大全| 国产精品欧美一级免费| 国产一区二区三区18| 日本不卡高清视频| 欧洲福利电影| 精品国产一级| 日韩亚洲欧美视频| 91亚洲国产成人精品性色| 红桃视频成人在线观看| 麻豆视频观看网址久久| 欧美成人综合| 极品尤物久久久av免费看| 日韩电影精品| 欧美电影免费观看高清完整| 国产一级在线| 二区三区四区高清视频在线观看| 传媒视频在线| 欧美12一14sex性hd| 污污网站在线| 日本高清中文字幕二区在线| 春日野结衣av| 成人18免费| 色免费在线视频| 精品少妇无遮挡毛片| 97超碰在线人人| 中文字幕2019第三页| 黄色www网站| 波多野结衣 作品| 男人的天堂日韩| 五月天婷婷激情视频| www.久草| 日本中文字幕在线视频观看 | 日韩视频在线免费观看| 亚洲最大的成人av| 欧美一区二区三区免费大片 | 96av在线| 四虎精品一区二区免费| 高清在线一区| 国产在线视频网| 成人免费在线观看| 色网在线视频| 快射av在线播放一区| 日本久久免费| 国产视频一区二区| 在线观看av每日更新免费| 中文字幕免费高| 正在播放91九色| 欧美一级二级三级九九九| 在线日韩欧美视频| 欧美成人a∨高清免费观看| 亚洲欧美日韩国产手机在线| 欧美性猛交xxxx乱大交极品| 一区二区国产精品视频| 日韩禁在线播放| 日韩欧美一区在线| 日韩欧美国产一区二区在线播放 | 日韩欧美在线网址| 欧美日本一区二区在线观看| 高清国产一区| 久草在线资源视频在线观看|