亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

[Java并發(fā)-7]java的線程小節(jié)

Sunxb / 2423人閱讀

摘要:在領(lǐng)域,實(shí)現(xiàn)并發(fā)程序的主要手段就是多線程??蛇\(yùn)行狀態(tài)指的是線程可以分配執(zhí)行。當(dāng)?shù)却氖录霈F(xiàn)了,線程就會(huì)從休眠狀態(tài)轉(zhuǎn)換到可運(yùn)行狀態(tài)。導(dǎo)出線程棧,分析線程狀態(tài)是診斷并發(fā)問題的一個(gè)重要工具。

在 Java 領(lǐng)域,實(shí)現(xiàn)并發(fā)程序的主要手段就是多線程。線程是操作系統(tǒng)里的一個(gè)概念,雖然各種不同的開發(fā)語(yǔ)言如 Java、C# 等都對(duì)其進(jìn)行了封裝,但原理和思路都是相同都。Java 語(yǔ)言里的線程本質(zhì)上就是操作系統(tǒng)的線程,它們是一一對(duì)應(yīng)的。

在操作系統(tǒng)層面,線程也有“生老病死”,專業(yè)的說法叫有生命周期。對(duì)于有生命周期的事物,要學(xué)好它,只要能搞懂生命周期中各個(gè)節(jié)點(diǎn)的狀態(tài)轉(zhuǎn)換機(jī)制就可以了。

雖然不同的開發(fā)語(yǔ)言對(duì)于操作系統(tǒng)線程進(jìn)行了不同的封裝,但是對(duì)于線程的生命周期這部分,基本上是雷同的。所以,我們可以先來了解一下通用的線程生命周期模型,然后再詳細(xì)的學(xué)習(xí)一下 Java 中線程的生命周期。

通用的線程生命周期

通用的線程生命周期基本上可以用下圖這個(gè)“五態(tài)模型”來描述。這五態(tài)分別是:

初始狀態(tài)、可運(yùn)行狀態(tài)、運(yùn)行狀態(tài)、休眠狀態(tài) 和 終止?fàn)顟B(tài)


通用線程狀態(tài)轉(zhuǎn)換圖——五態(tài)模型

初始狀態(tài):指的是線程已經(jīng)被創(chuàng)建,但是還不允許分配 CPU 執(zhí)行。這個(gè)狀態(tài)屬于編程語(yǔ)言特有的,不過這里所謂的被創(chuàng)建,僅僅是在編程語(yǔ)言層面被創(chuàng)建,而在操作系統(tǒng)層面,真正的線程還沒有創(chuàng)建。

可運(yùn)行狀態(tài):指的是線程可以分配 CPU 執(zhí)行。在這種狀態(tài)下,真正的操作系統(tǒng)線程已經(jīng)被成功創(chuàng)建了,所以可以分配 CPU 執(zhí)行。

運(yùn)行狀態(tài):當(dāng)有空閑的 CPU 時(shí),操作系統(tǒng)會(huì)將其分配給一個(gè)處于可運(yùn)行狀態(tài)的線程,被分配到 CPU 的線程的狀態(tài)就轉(zhuǎn)換成了運(yùn)行狀態(tài)

休眠狀態(tài):運(yùn)行狀態(tài)的線程如果調(diào)用一個(gè)阻塞的 API(例如以阻塞方式讀文件)或者等待某個(gè)事件(例如條件變量),那么線程的狀態(tài)就會(huì)轉(zhuǎn)換到 休眠狀態(tài),同時(shí)釋放 CPU 使用權(quán),休眠狀態(tài)的線程永遠(yuǎn)沒有機(jī)會(huì)獲得 CPU 使用權(quán)。當(dāng)?shù)却氖录霈F(xiàn)了,線程就會(huì)從休眠狀態(tài)轉(zhuǎn)換到可運(yùn)行狀態(tài)。

終止?fàn)顟B(tài):線程執(zhí)行完或者出現(xiàn)異常就會(huì)進(jìn)入 終止?fàn)顟B(tài),終止?fàn)顟B(tài)的線程不會(huì)切換到其他任何狀態(tài),進(jìn)入終止?fàn)顟B(tài)也就意味著線程的生命周期結(jié)束了。

這五種狀態(tài)在不同編程語(yǔ)言里會(huì)有簡(jiǎn)化合并或者被細(xì)化。
Java 中線程的生命周期

Java 語(yǔ)言中線程共有六種狀態(tài),分別是:

NEW(初始化狀態(tài))

RUNNABLE(可運(yùn)行 / 運(yùn)行狀態(tài))

BLOCKED(阻塞狀態(tài))

WAITING(無時(shí)限等待)

TIMED_WAITING(有時(shí)限等待)

TERMINATED(終止?fàn)顟B(tài))

在操作系統(tǒng)層面,Java 線程中的 BLOCKED、WAITING、TIMED_WAITING 是一種狀態(tài),即前面我們提到的休眠狀態(tài)。也就是說

只要 Java 線程處于這三種狀態(tài)之一,那么這個(gè)線程就永遠(yuǎn)沒有 CPU 的使用權(quán)。

所以 Java 線程的生命周期可以簡(jiǎn)化為下圖:


Java 中的線程狀態(tài)轉(zhuǎn)換圖

其中,BLOCKED、WAITING、TIMED_WAITING 可以理解為線程導(dǎo)致休眠狀態(tài)的三種原因。那具體是哪些情形會(huì)導(dǎo)致線程從 RUNNABLE 狀態(tài)轉(zhuǎn)換到這三種狀態(tài)呢?而這三種狀態(tài)又是何時(shí)轉(zhuǎn)換回 RUNNABLE 的呢?以及 NEW、TERMINATED 和 RUNNABLE 狀態(tài)是如何轉(zhuǎn)換的?

1. RUNNABLE 與 BLOCKED 的狀態(tài)轉(zhuǎn)換

只有一種場(chǎng)景會(huì)觸發(fā)這種轉(zhuǎn)換,就是線程等待 synchronized 的隱式鎖。synchronized 修飾的方法、代碼塊同一時(shí)刻只允許一個(gè)線程執(zhí)行,其他線程只能等待,這種情況下,等待的線程就會(huì)從 RUNNABLE 轉(zhuǎn)換到 BLOCKED 狀態(tài)。而當(dāng)?shù)却木€程獲得 synchronized 隱式鎖時(shí),就又會(huì)從 BLOCKED 轉(zhuǎn)換到 RUNNABLE 狀態(tài)。

如果你熟悉操作系統(tǒng)線程的生命周期的話,可能會(huì)有個(gè)疑問:線程調(diào)用阻塞式 API 時(shí),是否會(huì)轉(zhuǎn)換到 BLOCKED 狀態(tài)呢?在操作系統(tǒng)層面,線程是會(huì)轉(zhuǎn)換到休眠狀態(tài)的,但是在 JVM 層面,Java 線程的狀態(tài)不會(huì)發(fā)生變化,也就是說 Java 線程的狀態(tài)會(huì)依然保持 RUNNABLE 狀態(tài)。

JVM 層面并不關(guān)心操作系統(tǒng)調(diào)度相關(guān)的狀態(tài) ,因?yàn)樵?JVM 看來,等待 CPU 使用權(quán)(操作系統(tǒng)層面此時(shí)處于可執(zhí)行狀態(tài))與等待 I/O(操作系統(tǒng)層面此時(shí)處于休眠狀態(tài))沒有區(qū)別,都是在等待某個(gè)資源,所以都?xì)w入了 RUNNABLE 狀態(tài)。

而我們平時(shí)所謂的 Java 在調(diào)用阻塞式 API 時(shí),線程會(huì)阻塞,指的是操作系統(tǒng)線程的狀態(tài),并不是 Java 線程的狀態(tài)。

2. RUNNABLE 與 WAITING 的狀態(tài)轉(zhuǎn)換

有三種場(chǎng)景會(huì)觸發(fā)這種轉(zhuǎn)換。

第一種場(chǎng)景,獲得 synchronized 隱式鎖的線程,調(diào)用無參數(shù)的 Object.wait() 方法。

第二種場(chǎng)景,調(diào)用無參數(shù)的 Thread.join() 方法。其中的 join() 是一種線程同步方法,例如有一個(gè)線程對(duì)象 thread A,當(dāng)調(diào)用 A.join() 的時(shí)候,執(zhí)行這條語(yǔ)句的線程會(huì)等待 thread A 執(zhí)行完,而等待中的這個(gè)線程,其狀態(tài)會(huì)從 RUNNABLE 轉(zhuǎn)換到 WAITING。當(dāng)線程 thread A 執(zhí)行完,原來等待它的線程又會(huì)從 WAITING 狀態(tài)轉(zhuǎn)換到 RUNNABLE。

第三種場(chǎng)景,調(diào)用 LockSupport.park() 方法。其中的 LockSupport 對(duì)象,也許你有點(diǎn)陌生,其實(shí) Java 并發(fā)包中的鎖,都是基于它實(shí)現(xiàn)的。調(diào)用 LockSupport.park() 方法,當(dāng)前線程會(huì)阻塞,線程的狀態(tài)會(huì)從 RUNNABLE 轉(zhuǎn)換到 WAITING。調(diào)用 LockSupport.unpark(Thread thread) 可喚醒目標(biāo)線程,目標(biāo)線程的狀態(tài)又會(huì)從 WAITING 狀態(tài)轉(zhuǎn)換到 RUNNABLE。

3. RUNNABLE 與 TIMED_WAITING 的狀態(tài)轉(zhuǎn)換

有五種場(chǎng)景會(huì)觸發(fā)這種轉(zhuǎn)換:

調(diào)用帶超時(shí)參數(shù)的 Thread.sleep(long millis) 方法;

獲得 synchronized 隱式鎖的線程,調(diào)用帶超時(shí)參數(shù)的 Object.wait(long timeout) 方法;

調(diào)用帶超時(shí)參數(shù)的 Thread.join(long millis) 方法;

調(diào)用帶超時(shí)參數(shù)的 LockSupport.parkNanos(Object blocker, long deadline) 方法;

調(diào)用帶超時(shí)參數(shù)的 LockSupport.parkUntil(long deadline) 方法。

TIMED_WAITING 和 WAITING 狀態(tài)的區(qū)別,僅僅是觸發(fā)條件多了 超時(shí)參數(shù)。

4. 從 NEW 到 RUNNABLE 狀態(tài)

Java 剛創(chuàng)建出來的 Thread 對(duì)象就是 NEW 狀態(tài),而創(chuàng)建 Thread 對(duì)象主要有兩種方法。一種是繼承 Thread 對(duì)象,重寫 run() 方法。示例代碼如下:

// 自定義線程對(duì)象
class MyThread extends Thread {
  public void run() {
    // 線程需要執(zhí)行的代碼
    ......
  }
}
// 創(chuàng)建線程對(duì)象
MyThread myThread = new MyThread();

另一種是實(shí)現(xiàn) Runnable 接口,重寫 run() 方法,并將該實(shí)現(xiàn)類作為創(chuàng)建 Thread 對(duì)象的參數(shù)。示例代碼如下:

// 實(shí)現(xiàn) Runnable 接口
class Runner implements Runnable {
  @Override
  public void run() {
    // 線程需要執(zhí)行的代碼
    ......
  }
}
// 創(chuàng)建線程對(duì)象
Thread thread = new Thread(new Runner());

NEW 狀態(tài)的線程,不會(huì)被操作系統(tǒng)調(diào)度,因此不會(huì)執(zhí)行。Java 線程要執(zhí)行,就必須轉(zhuǎn)換到 RUNNABLE 狀態(tài)。從 NEW 狀態(tài)轉(zhuǎn)換到 RUNNABLE 狀態(tài)很簡(jiǎn)單,只要調(diào)用線程對(duì)象的 start() 方法就可以了,示例代碼如下:

MyThread myThread = new MyThread();
// 從 NEW 狀態(tài)轉(zhuǎn)換到 RUNNABLE 狀態(tài)
myThread.start();
5. 從 RUNNABLE 到 TERMINATED 狀態(tài)

線程執(zhí)行完 run() 方法后,會(huì)自動(dòng)轉(zhuǎn)換到 TERMINATED 狀態(tài),當(dāng)然如果執(zhí)行 run() 方法的時(shí)候異常拋出,也會(huì)導(dǎo)致線程終止。有時(shí)候我們需要強(qiáng)制中斷 run() 方法的執(zhí)行,例如 run() 方法訪問一個(gè)很慢的網(wǎng)絡(luò),我們等不下去了,想終止怎么辦呢?Java 的 Thread 類里面倒是有個(gè) stop() 方法,不過已經(jīng)標(biāo)記為 @Deprecated,所以不建議使用了。正確的姿勢(shì)其實(shí)是調(diào)用 interrupt() 方法。

stop() 和 interrupt() 方法的主要區(qū)別?

stop() 方法會(huì)真的殺死線程,不給線程喘息的機(jī)會(huì),如果線程持有 ReentrantLock 鎖,被 stop() 的線程并不會(huì)自動(dòng)調(diào)用 ReentrantLock 的 unlock() 去釋放鎖,那其他線程就再也沒機(jī)會(huì)獲得 ReentrantLock 鎖。所以該方法就不建議使用了,類似的方法還有 suspend() 和 resume() 方法,這兩個(gè)方法同樣也都不建議使用。

而 interrupt() 方法僅僅是通知線程,線程有機(jī)會(huì)執(zhí)行一些后續(xù)操作,同時(shí)也可以無視這個(gè)通知。被 interrupt 的線程,是怎么收到通知的呢?一種是異常,另一種是主動(dòng)檢測(cè)。

當(dāng)線程 A 處于 WAITING、TIMED_WAITING 狀態(tài)時(shí),如果其他線程調(diào)用線程 A 的 interrupt() 方法,會(huì)使線程 A 返回到 RUNNABLE 狀態(tài),同時(shí)線程 A 的代碼會(huì)觸發(fā) InterruptedException 異常。上面我們提到轉(zhuǎn)換到 WAITING、TIMED_WAITING 狀態(tài)的觸發(fā)條件,都是調(diào)用了類似 wait()、join()、sleep() 這樣的方法,我們看這些方法的簽名,發(fā)現(xiàn)都會(huì) throws InterruptedException 這個(gè)異常。這個(gè)異常的觸發(fā)條件就是:其他線程調(diào)用了該線程的 interrupt() 方法。

當(dāng)線程 A 處于 RUNNABLE 狀態(tài)時(shí),并且阻塞在 java.nio.channels.InterruptibleChannel 上時(shí),如果其他線程調(diào)用線程 A 的 interrupt() 方法,線程 A 會(huì)觸發(fā) java.nio.channels.ClosedByInterruptException 這個(gè)異常;而阻塞在 java.nio.channels.Selector 上時(shí),如果其他線程調(diào)用線程 A 的 interrupt() 方法,線程 A 的 java.nio.channels.Selector 會(huì)立即返回。

還有一種是主動(dòng)檢測(cè),如果線程處于 RUNNABLE 狀態(tài),并且沒有阻塞在某個(gè) I/O 操作上,例如中斷計(jì)算圓周率的線程 A,這時(shí)就得依賴線程 A 主動(dòng)檢測(cè)中斷狀態(tài)了。如果其他線程調(diào)用線程 A 的 interrupt() 方法,那么線程 A 可以通過 isInterrupted() 方法,檢測(cè)是不是自己被中斷了。

Java線程的生命周期小結(jié)

多線程程序很難調(diào)試,出了 Bug 基本上都是靠日志,靠線程 dump 來跟蹤問題,分析線程 dump 的一個(gè)基本功就是分析線程狀態(tài),大部分的死鎖、饑餓、活鎖問題都需要跟蹤分析線程的狀態(tài)。

通過 jstack 命令或者 Java VisualVM 這個(gè)可視化工具將 JVM 所有的線程棧信息導(dǎo)出來,完整的線程棧信息不僅包括線程的當(dāng)前狀態(tài)、調(diào)用棧,還包括了鎖的信息。導(dǎo)出線程棧,分析線程狀態(tài)是診斷并發(fā)問題的一個(gè)重要工具。

創(chuàng)建多少線程才是合適的?

在 Java 領(lǐng)域,實(shí)現(xiàn)并發(fā)程序的主要手段就是多線程,使用多線程還是比較簡(jiǎn)單的,但是使用多少個(gè)線程卻是個(gè)困難的問題。工作中,經(jīng)常有人問,“各種線程池的線程數(shù)量調(diào)整成多少是合適的?

要解決這個(gè)問題,首先要分析以下兩個(gè)問題:

為什么要使用多線程?

多線程的應(yīng)用場(chǎng)景有哪些?

為什么使用多線程

使用多線程,本質(zhì)上就是提升程序性能。不過此刻談到的性能,首要問題是:如何度量性能。

度量性能的指標(biāo)有很多,但是有兩個(gè)指標(biāo)是最核心的,它們就是延遲和吞吐量。
延遲指的是發(fā)出請(qǐng)求到收到響應(yīng)這個(gè)過程的時(shí)間;延遲越短,意味著程序執(zhí)行得越快,性能也就越好。
吞吐量指的是在單位時(shí)間內(nèi)能處理請(qǐng)求的數(shù)量;吞吐量越大,意味著程序能處理的請(qǐng)求越多,性能也就越好。這兩個(gè)指標(biāo)內(nèi)部有一定的聯(lián)系(同等條件下,延遲越短,吞吐量越大),但是由于它們隸屬不同的維度(一個(gè)是時(shí)間維度,一個(gè)是空間維度),并不能互相轉(zhuǎn)換。

我們所謂提升性能,從度量的角度,主要是降低延遲,提高吞吐量。這也是我們使用多線程的主要目的。那我們?cè)撛趺唇档脱舆t,提高吞吐量呢?這個(gè)就要從多線程的應(yīng)用場(chǎng)景說起了。

多線程的應(yīng)用場(chǎng)景

要想“降低延遲,提高吞吐量”,對(duì)應(yīng)的方法呢,基本上有兩個(gè)方向,一個(gè)方向是優(yōu)化算法,另一個(gè)方向是 將硬件的性能發(fā)揮到極致。前者屬于算法范疇,后者則是和并發(fā)編程相關(guān)了。其實(shí)計(jì)算機(jī)主要有主要是兩類:一個(gè)是 I/O,一個(gè)是 CPU。簡(jiǎn)言之,在并發(fā)編程領(lǐng)域,提升性能本質(zhì)上就是提升 I/O 的利用率和 CPU 的利用率。多帶帶來看,操作系統(tǒng)已經(jīng)為我們做了利用率的優(yōu)化了,但是解決的是針對(duì)單一的硬件利用率。我們的程序執(zhí)行中是既要CPU也要I/O的。所以對(duì)于我們開發(fā)者,我們最終需要解決 CPU 和 I/O 設(shè)備綜合利用率的問題。

下面我們用一個(gè)簡(jiǎn)單的示例來說明:如何利用多線程來提升 CPU 和 I/O 設(shè)備的利用率?假設(shè)程序按照 CPU 計(jì)算和 I/O 操作交叉執(zhí)行的方式運(yùn)行,而且 CPU 計(jì)算和 I/O 操作的耗時(shí)是 1:1。

如下圖所示,如果只有一個(gè)線程,執(zhí)行 CPU 計(jì)算的時(shí)候,I/O 設(shè)備空閑;執(zhí)行 I/O 操作的時(shí)候,CPU 空閑,所以 CPU 的利用率和 I/O 設(shè)備的利用率都是 50%。

如果有兩個(gè)線程,如下圖所示,當(dāng)線程 A 執(zhí)行 CPU 計(jì)算的時(shí)候,線程 B 執(zhí)行 I/O 操作;當(dāng)線程 A 執(zhí)行 I/O 操作的時(shí)候,線程 B 執(zhí)行 CPU 計(jì)算,這樣 CPU 的利用率和 I/O 設(shè)備的利用率就都達(dá)到了 100%。

通過上面的圖示,很容易看出:?jiǎn)挝粫r(shí)間處理的請(qǐng)求數(shù)量翻了一番,也就是說吞吐量提高了 1 倍。此時(shí)可以逆向思維一下,如果 CPU 和 I/O 設(shè)備的利用率都很低,那么可以嘗試通過增加線程來提高吞吐量.

創(chuàng)建多少線程合適?

創(chuàng)建多少線程合適,要看多線程具體的應(yīng)用場(chǎng)景。我們的程序一般都是 CPU 計(jì)算和 I/O 操作交叉執(zhí)行的,由于 I/O 設(shè)備的速度相對(duì)于 CPU 來說都很慢,所以大部分情況下,I/O 操作執(zhí)行的時(shí)間相對(duì)于 CPU 計(jì)算來說都非常長(zhǎng),這種場(chǎng)景我們一般都稱為 I/O 密集型計(jì)算;和 I/O 密集型計(jì)算相對(duì)的就是 CPU 密集型計(jì)算了,CPU 密集型計(jì)算大部分場(chǎng)景下都是純 CPU 計(jì)算。I/O 密集型程序和 CPU 密集型程序,計(jì)算最佳線程數(shù)的方法是不同的。

對(duì)于 CPU 密集型計(jì)算,多線程本質(zhì)上是提升多核 CPU 的利用率,所以對(duì)于一個(gè) 4 核的 CPU,每個(gè)核一個(gè)線程,理論上創(chuàng)建 4 個(gè)線程就可以了,再多創(chuàng)建線程也只是增加線程切換的成本。所以,

對(duì)于 CPU 密集型的計(jì)算場(chǎng)景,理論上“線程的數(shù)量 =CPU 核數(shù)”就是最合適的。不過在工程上,線程的數(shù)量一般會(huì)設(shè)置為“CPU 核數(shù) +1”

因?yàn)楫?dāng)線程因?yàn)榕紶柕膬?nèi)存頁(yè)失效或其他原因?qū)е伦枞麜r(shí),這個(gè)額外的線程可以頂上,從而保證 CPU 的利用率。

對(duì)于 I/O 密集型的計(jì)算場(chǎng)景,比如前面我們的例子中,如果 CPU 計(jì)算和 I/O 操作的耗時(shí)是 1:1,那么 2 個(gè)線程是最合適的。如果 CPU 計(jì)算和 I/O 操作的耗時(shí)是 1:2,那多少個(gè)線程合適呢?是 3 個(gè)線程,如下圖所示:CPU 在 A、B、C 三個(gè)線程之間切換,對(duì)于線程 A,當(dāng) CPU 從 B、C 切換回來時(shí),線程 A 正好執(zhí)行完 I/O 操作。這樣 CPU 和 I/O 設(shè)備的利用率都達(dá)到了 100%。

三線程執(zhí)行示意圖

通過上面這個(gè)例子,我們會(huì)發(fā)現(xiàn),對(duì)于 I/O 密集型計(jì)算場(chǎng)景,最佳的線程數(shù)是與程序中 CPU 計(jì)算和 I/O 操作的耗時(shí)比相關(guān)的,我們可以總結(jié)出這樣一個(gè)公式:

最佳線程數(shù) =1 +(I/O 耗時(shí) / CPU 耗時(shí))

我們令 R=I/O 耗時(shí) / CPU 耗時(shí),綜合上圖,可以這樣理解:當(dāng)線程 A 執(zhí)行 IO 操作時(shí),另外 R 個(gè)線程正好執(zhí)行完各自的 CPU 計(jì)算。這樣 CPU 的利用率就達(dá)到了 100%。

多核 CPU,只需要等比擴(kuò)大就可以了,計(jì)算公式如下:

最佳線程數(shù) =CPU 核數(shù) * [ 1 +(I/O 耗時(shí) / CPU 耗時(shí))]
線程多少的總結(jié)

對(duì)于 I/O 密集型計(jì)算場(chǎng)景,I/O 耗時(shí)和 CPU 耗時(shí)的比值是一個(gè)關(guān)鍵參數(shù),不幸的是這個(gè)參數(shù)是未知的,而且是動(dòng)態(tài)變化的,所以工程上,我們要估算這個(gè)參數(shù),然后做各種不同場(chǎng)景下的壓測(cè)來驗(yàn)證我們的估計(jì)。所以壓測(cè)時(shí),我們需要重點(diǎn)關(guān)注 CPU、I/O 設(shè)備的利用率和性能指標(biāo)(響應(yīng)時(shí)間、吞吐量)之間的關(guān)系。
耗時(shí)的比值需要使用APM工具觀察得出。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/77628.html

相關(guān)文章

  • 并發(fā)編程藝術(shù)

    摘要:假設(shè)不發(fā)生編譯器重排和指令重排,線程修改了的值,但是修改以后,的值可能還沒有寫回到主存中,那么線程得到就是很自然的事了。同理,線程對(duì)于的賦值操作也可能沒有及時(shí)刷新到主存中。線程的最后操作與線程發(fā)現(xiàn)線程已經(jīng)結(jié)束同步。 很久沒更新文章了,對(duì)隔三差五過來刷更新的讀者說聲抱歉。 關(guān)于 Java 并發(fā)也算是寫了好幾篇文章了,本文將介紹一些比較基礎(chǔ)的內(nèi)容,注意,閱讀本文需要一定的并發(fā)基礎(chǔ)。 本文的...

    curlyCheng 評(píng)論0 收藏0
  • Java? 教程(執(zhí)行器)

    執(zhí)行器 在前面的所有示例中,由新的線程(由其Runnable對(duì)象定義)和線程本身(由Thread對(duì)象定義)完成的任務(wù)之間存在緊密的聯(lián)系,這適用于小型應(yīng)用程序,但在大型應(yīng)用程序中,將線程管理和創(chuàng)建與應(yīng)用程序的其余部分分開是有意義的,封裝這些函數(shù)的對(duì)象稱為執(zhí)行器,以下小節(jié)詳細(xì)描述了執(zhí)行器。 執(zhí)行器接口定義三個(gè)執(zhí)行器對(duì)象類型。 線程池是最常見的執(zhí)行器實(shí)現(xiàn)類型。 Fork/Join是一個(gè)利用多個(gè)處理器的...

    馬忠志 評(píng)論0 收藏0
  • java虛擬機(jī)

    摘要:虛擬機(jī)棧線程私有,生命周期跟線程相同。堆用于存放對(duì)象實(shí)例,是虛擬機(jī)所管理的內(nèi)存中最大的一塊,同時(shí)也是所有線程共享的一塊內(nèi)存區(qū)域。統(tǒng)計(jì)監(jiān)測(cè)工具語(yǔ)法格式如下是虛擬機(jī),在系統(tǒng)上一般就是進(jìn)程。 JDK、JRE、JVM三者的關(guān)系 JDK(Java Development Kit)是針對(duì)Java開發(fā)的產(chǎn)品、是整個(gè)Java的核心,包括Java運(yùn)行環(huán)境JRE、Java工具包和Java基礎(chǔ)類庫(kù)。 JR...

    趙春朋 評(píng)論0 收藏0
  • [譯]GC專家系列1:理解Java垃圾回收

    摘要:本文是成為專家系列的第一篇。然而,在多線程環(huán)境下,將會(huì)有別樣的狀況。在中正是通過解決了多線程問題。在最后的并發(fā)清理階段,垃圾回收過程被真正執(zhí)行。在垃圾回收?qǐng)?zhí)行過程中,其他線程依然在執(zhí)行。 原文鏈接:http://www.cubrid.org/blog/de... 了解Java的垃圾回收(GC)原理能給我們帶來什么好處?對(duì)于軟件工程師來說,滿足技術(shù)好奇心可算是一個(gè),但重要的是理解GC能幫...

    diabloneo 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<