日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java并发编程艺术读书笔记

發(fā)布時間:2023/11/29 java 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java并发编程艺术读书笔记 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

1、多線程在CPU切換過程中,由于需要保存線程之前狀態(tài)和加載新線程狀態(tài),成為上下文切換,上下文切換會造成消耗系統(tǒng)內(nèi)存。所以,可合理控制線程數(shù)量。 如何控制:

  (1)使用ps -ef|grep appname,查找appname的pid;如1111

  (2)使用jstack 1111 > /home/ibethfy/dump1,將dump信息追加到dump1

  (3)使用grep java.lang.Thread.State /home/ibethfy/dump1 | awk '{print $2$3$4$5}' | sort | uniq -c,統(tǒng)計查找線程狀態(tài)個數(shù)。分析是否WAITING的線程過多。

  (4)查看這些WAITING的線程時怎么產(chǎn)生的,如某個服務創(chuàng)建線程池中線程過多,分析后對應修改。

  (5)重啟后重新統(tǒng)計。

2、避免死鎖幾種常用方式

  (1)避免一個線程同時獲取多個鎖。

  (2)避免一個線程在鎖內(nèi)同時占用多個資源,盡量保證每個鎖只占用一個資源。

  (3)嘗試使用定時鎖,lock.tryLock(timeout)來替代內(nèi)部鎖機制。

  (4)對于數(shù)據(jù)庫鎖,加鎖和解鎖必須在同一個連接內(nèi),不然會造成解鎖失敗的情況。

3、volatile保證共享資源對其他線程的可見性。volatile修飾共享變量時,共享變量進行寫操作時,會在匯編中多一個lock前綴的指令,該指定表示要將該變量從當前處理器的緩存行數(shù)據(jù)寫到系統(tǒng)內(nèi)存,寫會內(nèi)存操作會使其他CPU緩存了該內(nèi)存地址的數(shù)據(jù)失效。其他CPU去獲取該數(shù)據(jù)時,會從系統(tǒng)內(nèi)存重新獲取。

4、synchronized,JVM通過進入和退出Monitor對象來實現(xiàn)代碼塊和方法同步。代碼塊同步使用的是monitorenter和monitorexit來實現(xiàn)。在編譯時,會將這兩個指令分別插入到代碼塊開始和結(jié)束(包括正常和異常結(jié)束),在執(zhí)行這兩句指令時,會去進去和退出monitor對象。

5、鎖在哪?Java的鎖,是存在對象頭的Mark Word中。存儲一個鎖地址,指向C++里面的一個ObjectMonitor對象,該對象存儲了當前占用鎖的線程,等待的線程,該線程重入的次數(shù),鎖狀態(tài)等字段。

6、JMM,Java內(nèi)存模型,用于控制Java線程之間的通信,和計算機多線程模型類似,也是為每個線程分配了類似的內(nèi)存緩存,變量存在主內(nèi)存中,要保證線程之間的通信,必須要保證線程A將數(shù)據(jù)從本地緩存刷新到主內(nèi)存,線程B識別到數(shù)據(jù)更新,從主內(nèi)存中取得最新數(shù)據(jù)。JMM主要就是控制主內(nèi)存和線程本地內(nèi)存之間的交互等。

7、JMM模型中,主要是解決有序性(順序一致性),可見性,原子性。

  (1)由于多線程中,每個線程有自己的本地緩存,且在執(zhí)行代碼后,不知道何時回把緩存刷新到主內(nèi)存,所以,線程的操作對其他線程是不可見的。這時不同線程獲取共享變量就會出現(xiàn)不一致的問題。

  (2)指令的重排序:重排序是指編譯器和處理器為了優(yōu)化程序性能而對指令序列進行重新排序的一種手段。數(shù)據(jù)依賴性:某一行代碼依賴上一行代碼,這樣不會進行這兩條代碼的重排序,多線程系統(tǒng)不會考慮該問題。順序一致性:指令重排序后,最終執(zhí)行結(jié)果要和順序執(zhí)行結(jié)果一致。

  (3)多線程之間進行了正確的數(shù)據(jù)同步,JMM保證多個線程的順序一致性。

  (4)順序一致性模型:一個程序的操作必須按照程序順序執(zhí)行。不管程序是否同步,所有線程都能按照單一的操作執(zhí)行順序。即多個線程的操作可以并行執(zhí)行,但對于單個線程來看,他的指令時順序執(zhí)行的,且每條指令都對其他線程可見。

  (5)JMM不保證順序一致性,即未同步的線程,執(zhí)行順序是無序的,且可能對其他內(nèi)存不可見。這個時候,就需要同步來實現(xiàn)順序一致性模型。synchronized修飾的代碼塊,在獲得鎖后才能執(zhí)行,從而保證了多個線程的整體順序執(zhí)行,但同步塊局部不依賴的指令,也可進行重排序(盡量給編譯器或者優(yōu)化器優(yōu)化提供入口)。為什么JMM不保證未同步的線程的順序一致性呢?主要是要保證會禁止大量的編譯器等優(yōu)化,嚴重影響性能,所以就提供同步方法來實現(xiàn)。

  (6)JMM內(nèi)存可見性的保證:單線程不會出現(xiàn)內(nèi)存可見性問題,編譯器,runtime,處理器會共同保證期執(zhí)行結(jié)果和順序一致性模型結(jié)果一致;多線程,正確同步的多線程將具有順序一致性,JMM通過限制編譯器和處理器的重排序來提供內(nèi)存可見性的保證。未同步或未正確同步的多線程,JMM為他們提供了最小安全性的保證,線程讀取到的值,要么是之前線程寫入的值,要么是初始值。

  (7)volatile,當寫volatile時,其他讀寫指令在其之后執(zhí)行,保證了有序性;當寫時,會把新的緩存中的值寫入到主內(nèi)存;另一線程讀時,會將本地緩存地址置為無效,從主內(nèi)存中獲取該值。

  (8)synchronized,當某線程獲得鎖時,其余線程等待,保證了有序性。當某線程釋放鎖時,會將本地緩存寫入主內(nèi)存,當另一線程獲取鎖時,會將本地緩存置為無效,從主內(nèi)存獲取數(shù)據(jù)。所以保證了多線程的順序一致性和可見性。

  (9)happens-before規(guī)則。

8、wait和notify:WaitThread首先獲取了對象的鎖,然后調(diào)用鎖對象的wait()方法,從而放棄了鎖并進入了對象的等待隊列WaitQueue中,進入等待狀態(tài)。由于WaitThread釋放了對象的鎖,NotifyThread隨后獲取了對象的鎖,并調(diào)用鎖對象的notify()方法,將WaitThread從WaitQueue移到SynchronizedQueue中,此時WaitThread的狀態(tài)變?yōu)樽枞麪顟B(tài)。NotifyThread釋放了鎖之后,WaitThread再次獲取到鎖并從wait()方法返回繼續(xù)執(zhí)行。金典案例如下: synchronized(對象)?{ ???????

  while(條件不滿足)?{ ?????????????

    ?對象.wait(); ?????

  ??} ?????

?  ?對應的處理邏輯

}

synchronized(對象)?{

???????改變條件 ???????

  對象.notifyAll();

}

9、ThreadLocal:ThreadLocal,即線程變量,是一個以ThreadLocal線程對象為鍵、任意對象為值的存儲結(jié)構(gòu)。這個結(jié)構(gòu)被附帶在線程上,也就是說一個線程可以根據(jù)一個ThreadLocal對象查詢到綁定在這個線程上的一個值。

10、CountDownLatch:

  (1)、初始化CountDownLatch cdl? = new CountDownLatch(5);

  (2)、同一線程或多個線程調(diào)用cdl.countDown(),使計數(shù)器減一,通過入?yún)魅隿dl;等待線程調(diào)用cdl.await(),阻塞等待cdl計數(shù)器等于0后,執(zhí)行。

11、CyclicBarrier:

  (1)、初始化CyclicBarrier cb = new CyclicBarrier();

  (2)、其余線程調(diào)用cb.await(),告訴屏障我已到達,然后等待指定數(shù)量的線程都已到達后,然后統(tǒng)一往后執(zhí)行。

  (3)、構(gòu)造函數(shù)可傳入另一線程,表示到達屏障的數(shù)量滿足后,優(yōu)先執(zhí)行該方法。

12、Semaphore:Semaphore(10)表示允許10個線程獲取許可證,也就是最大并發(fā)數(shù)是10。Semaphore的用法也很簡單,首先線程使用Semaphore的acquire()方法獲取一個許可證,使用完之后調(diào)用release()方法歸還許可證。還可以用tryAcquire()方法嘗試獲取許可證。

13、Exchanger:用于線程間數(shù)據(jù)交換。

14、線程池技術:好處

  (1)降低系統(tǒng)消耗,重復利用線程

  (2)提高響應速度,不用重新創(chuàng)建線程

  (3)提高可管理性,可以實現(xiàn)對線程的管理。

線程池流程:

  (1)新來一個任務,如果沒有超過核心線程數(shù),則創(chuàng)建一個核心線程,執(zhí)行任務,不管是否有閑置的核心線程,也會創(chuàng)建新的核心線程執(zhí)行任務。

  (2)如果核心線程都處于運行狀態(tài),且數(shù)量已達上限,則判斷工作隊列是否已滿,如果未滿,則將任務加入工作隊列,排隊等待核心線程空閑后執(zhí)行。

  (3)如果核心線程都在運行任務和工作隊列都滿了,則創(chuàng)建新的額外線程來執(zhí)行任務。(額外線程由最大線程決定,且無用后會被回收)

  (4)額外線程也滿了且都在執(zhí)行的話,就采用拒絕策略拒絕請求。

線程池創(chuàng)建參數(shù):

  (1)corePoolSize,核心線程數(shù)量。

  (2)runnableTaskQueue:任務隊列,有ArrayBlockingQueue,基于數(shù)組的有界阻塞隊列,FIFO;LinkedBlockingQueue,基于鏈表實現(xiàn)的阻塞隊列,FIFO,吞吐量通常高于ArrayBlockingQueue,靜態(tài)工廠方法Executors.newFixedThreadPool()使用了這個隊列;SynchronousQueue:一個不存儲元素的阻塞隊列。每個插入操作必須等到另一個線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài),吞吐量通常要高于Linked-BlockingQueue,靜態(tài)工廠方法Executors.newCachedThreadPool使用了這個隊列;

  (3)maximumPoolSize:線程池最大線程數(shù),線程池允許創(chuàng)建的最大線程數(shù)。如果隊列滿了,并且已創(chuàng)建的線程數(shù)小于最大線程數(shù),則線程池會再創(chuàng)建新的線程執(zhí)行任務。值得注意的是,如果使用了無界的任務隊列這個參數(shù)就沒什么效果。

  (4)ThreadFactory:用于設置創(chuàng)建線程的工廠;

  (5)RejectedExecutionHandler(飽和策略):當隊列和線程池都滿了,說明線程池處于飽和狀態(tài),那么必須采取一種策略處理提交的新任務。這個策略默認情況下是AbortPolicy,表示無法處理新任務時拋出異常。以下四種策略: ·AbortPolicy:直接拋出異常。 ·CallerRunsPolicy:只用調(diào)用者所在線程來運行任務。 ·DiscardOldestPolicy:丟棄隊列里最近的一個任務,并執(zhí)行當前任務。 ·DiscardPolicy:不處理,丟棄掉

  (6)keepAliveTime(線程活動保持時間):線程池的工作線程空閑后(非核心線程會回收,allowCoreThreadTimeOut(true),設置這個屬性,核心線程在超時未用后,也會被回收),保持存活的時間。所以,如果任務很多,并且每個任務執(zhí)行的時間比較短,可以調(diào)大時間,提高線程的利用率。

  (7)TimeUnit(線程活動保持時間的單位);

轉(zhuǎn)載于:https://www.cnblogs.com/ibethfy/p/10119329.html

總結(jié)

以上是生活随笔為你收集整理的Java并发编程艺术读书笔记的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。