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

深入理解Java線程創(chuàng)建方式(最新推薦)

 更新時間:2025年10月27日 08:53:10   作者:阿瓜不瓜  
作為一名Java開發(fā)者,我深刻體會到,對線程的深入理解往往區(qū)分了初級和高級程序員,在這篇文章中,我將分享我對Java線程的個人理解,從基礎(chǔ)概念到底層實現(xiàn),希望能為你提供有價值的見解,感興趣的朋友跟隨小編一起看看吧

引言:為什么我們需要關(guān)注線程?

  在多核處理器成為主流的今天,我們手中的手機、電腦甚至智能家居設(shè)備都擁有多個計算核心。這意味著,如果我們的程序只能在一個核心上運行,就相當(dāng)于讓其他核心"閑置",無法充分發(fā)揮硬件性能。想象一下,一個餐廳只有一個服務(wù)員,即使廚房有多個廚師,顧客仍然需要排隊等待服務(wù)——這就是單線程程序的局限性。

  并發(fā)編程正是為了解決這個問題而生,而線程作為并發(fā)編程的基礎(chǔ)單元,理解其工作機制對于編寫高效、穩(wěn)定的應(yīng)用程序至關(guān)重要。作為一名Java開發(fā)者,我深刻體會到,對線程的深入理解往往區(qū)分了初級和高級程序員。在這篇博客中,我將分享我對Java線程的個人理解,從基礎(chǔ)概念到底層實現(xiàn),希望能為你提供有價值的見解。

一、線程與進程:本質(zhì)區(qū)別與內(nèi)在聯(lián)系

  在深入線程之前,我們需要從根本上理解線程與進程的區(qū)別。這個理解不能停留在表面,而要深入到操作系統(tǒng)層面。

進程:獨立的王國

 進程可以理解為一個獨立的"程序王國",每個王國都有自己獨立的領(lǐng)土(內(nèi)存空間)、資源(打開的文件、網(wǎng)絡(luò)連接等)和法律(安全上下文)。操作系統(tǒng)為每個進程分配獨立的虛擬地址空間,這意味著:

  進程A無法直接訪問進程B的內(nèi)存數(shù)據(jù)。

  進程崩潰通常不會影響其他進程。

  進程間通信需要特殊機制(管道、消息隊列、共享內(nèi)存等)。

線程:王國內(nèi)的協(xié)作團隊

線程則是同一個"王國"內(nèi)的不同"工作團隊",它們:

  共享王國的資源(內(nèi)存、文件描述符等)。

  各自執(zhí)行不同的任務(wù),但可以協(xié)作完成共同目標(biāo)。

  通信成本極低,因為可以直接訪問共享內(nèi)存。

技術(shù)視角的深度理解
  從操作系統(tǒng)角度看,進程是資源分配的實體,而線程是CPU調(diào)度的實體。當(dāng)我們在Java中創(chuàng)建線程時,實際上是在用戶態(tài)創(chuàng)建了一個線程控制塊,然后通過系統(tǒng)調(diào)用在內(nèi)核態(tài)創(chuàng)建對應(yīng)的內(nèi)核線程(在Linux中通過clone系統(tǒng)調(diào)用)。這就是為什么線程的創(chuàng)建和銷毀比進程輕量得多。

二、Java線程的創(chuàng)建方式:選擇背后的思考

1. 繼承Thread類:簡單但不推薦

class MyThread extends Thread {
@Override
public void run() {
System.out.println("線程執(zhí)行: " + Thread.currentThread().getName());
}
}

  這種方式看似簡單,但實際上存在設(shè)計上的問題。Java是單繼承語言,如果繼承了Thread類,就無法繼承其他類。這違反了"組合優(yōu)于繼承"的設(shè)計原則。此外,從任務(wù)執(zhí)行的角度看,線程的執(zhí)行體(run方法)和線程本身(Thread類)應(yīng)該是兩個關(guān)注點,這種方式將它們耦合在一起。

2. 實現(xiàn)Runnable接口:推薦的標(biāo)準做法

class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("線程執(zhí)行: " + Thread.currentThread().getName());
}
}

為什么這是更好的選擇?

  符合面向?qū)ο笤O(shè)計原則:任務(wù)與執(zhí)行機制分離。

  靈活性:可以繼承其他類,實現(xiàn)其他接口。

  可復(fù)用性:同一個Runnable實例可以被多個線程共享執(zhí)行。

3. 實現(xiàn)Callable接口:需要返回值的場景

class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "線程執(zhí)行結(jié)果: " + Thread.currentThread().getName();
}
}

核心價值:  

Callable的出現(xiàn)解決了Runnable無法返回結(jié)果和拋出受檢異常的問題。FutureTask作為RunnableFuture接口的實現(xiàn),既可以被Thread執(zhí)行,又可以通過Future接口獲取結(jié)果,這種設(shè)計體現(xiàn)了接口隔離原則。

4. 線程池方式:生產(chǎn)環(huán)境的必然選擇

ExecutorService executor = Executors.newFixedThreadPool(5);
Future<String> future = executor.submit(new MyCallable());

為什么線程池如此重要?直接創(chuàng)建線程的成本很高,包括:

  內(nèi)存分配:每個線程需要分配棧空間(默認512KB-1MB)。

  系統(tǒng)調(diào)用:需要內(nèi)核參與線程創(chuàng)建。

  資源管理:線程數(shù)量無限制增長會導(dǎo)致系統(tǒng)資源耗盡。

  線程池通過復(fù)用線程、控制并發(fā)數(shù)量、管理生命周期,解決了這些問題。

三、線程狀態(tài)與生命周期:狀態(tài)機的藝術(shù)

  理解線程的狀態(tài)轉(zhuǎn)換不僅僅是記住幾個狀態(tài)名稱,而是要理解每個狀態(tài)轉(zhuǎn)換的條件和意義。

狀態(tài)轉(zhuǎn)換的深度解析

NEW → RUNNABLE:(線程生命開始)
  當(dāng)調(diào)用start()方法時,線程從NEW狀態(tài)進入RUNNABLE狀態(tài)。這里有個重要細節(jié):start()方法只能調(diào)用一次,否則會拋出IllegalThreadStateException。這是因為線程的生命周期是不可逆的。

RUNNABLE → BLOCKED:(鎖競爭導(dǎo)致)
  這種情況通常發(fā)生在 synchronized 同步塊上。當(dāng)線程A持有鎖,線程B嘗試獲取同一個鎖時,線程B就會進入BLOCKED狀態(tài)。這里的關(guān)鍵理解是:BLOCKED狀態(tài)只與同步的monitor鎖相關(guān)。

RUNNABLE → WAITING:(主動等待)
有三種方法會導(dǎo)致這種轉(zhuǎn)換:

  Object.wait():釋放鎖并等待,需要其他線程調(diào)用notify()/notifyAll()

  Thread.join():等待目標(biāo)線程終止

  LockSupport.park():底層并發(fā)工具使用

RUNNABLE → TIMED_WAITING:(主動等待)
  與WAITING類似,但帶有超時時間。這是為了避免永久等待導(dǎo)致的死鎖。

實際開發(fā)中的意義:
  理解這些狀態(tài)轉(zhuǎn)換對于調(diào)試多線程問題至關(guān)重要。當(dāng)線程出現(xiàn)問題時,我們可以通過jstack等工具查看線程狀態(tài),快速定位問題原因。

四、線程同步與線程安全:秩序的藝術(shù)

可見性、原子性、有序性

在深入同步機制前,必須理解并發(fā)編程的三個核心問題:

  可見性:一個線程對共享變量的修改,其他線程能夠立即看到。由于CPU緩存的存在,線程可能讀取到過期的數(shù)據(jù)。

  原子性:一個或多個操作要么全部執(zhí)行成功,要么全部不執(zhí)行,不會出現(xiàn)中間狀態(tài)。

  有序性:程序執(zhí)行的順序按照代碼的先后順序執(zhí)行。由于指令重排序的存在,實際執(zhí)行順序可能與代碼順序不同。

synchronized的深度理解

public class SynchronizedDemo {
// 實例同步方法:鎖是當(dāng)前對象實例
public synchronized void instanceMethod() {
// 臨界區(qū)
}
// 靜態(tài)同步方法:鎖是當(dāng)前類的Class對象
public static synchronized void staticMethod() {
// 臨界區(qū)
}
// 同步代碼塊:可以指定任意對象作為鎖
public void someMethod() {
synchronized(this) {
// 臨界區(qū)
}
}
}

synchronized的實現(xiàn)原理:

  在字節(jié)碼層面,通過monitorenter和monitorexit指令實現(xiàn)。

  每個對象都有一個monitor(監(jiān)視器鎖)與之關(guān)聯(lián)。

  鎖具有可重入性:同一個線程可以多次獲取同一把鎖。

ReentrantLock:更靈活的鎖機制

public class ReentrantLockDemo {
private final ReentrantLock lock = new ReentrantLock(true); // 公平鎖
public void performTask() {
lock.lock(); // 可以在這里使用lockInterruptibly()支持中斷
try {
// 臨界區(qū)
} finally {
lock.unlock(); // 必須在finally塊中釋放鎖
}
}
}

與synchronized的對比:

特性

synchronized

ReentrantLock

實現(xiàn)機制

JVM內(nèi)置

JDK實現(xiàn)

鎖獲取

自動獲取釋放

手動控制

可中斷

不支持

支持

公平性

非公平

可選擇公平或非公平

條件變量

單一

多個

volatile關(guān)鍵字:輕量級的同步

public class VolatileExample {
private volatile boolean shutdown = false;
public void shutdown() {
shutdown = true; // 寫操作具有原子性和可見性
}
public void doWork() {
while (!shutdown) { // 讀操作總能獲取最新值
// 執(zhí)行任務(wù)
}
}
}

volatile的語義:

  可見性:對volatile變量的寫操作會立即刷新到主內(nèi)存。

  有序性:禁止指令重排序(內(nèi)存屏障)。

  不保證原子性:復(fù)合操作(如i++)仍然需要同步。

適用場景:

  狀態(tài)標(biāo)志位。

  雙重檢查鎖定模式。

  觀察者模式中的狀態(tài)發(fā)布。

五、線程間通信:協(xié)作的智慧

wait/notify機制:經(jīng)典的線程協(xié)作

public class WaitNotifyDemo {
private boolean condition = false;
public synchronized void waitForCondition() throws InterruptedException {
// 必須使用while循環(huán)檢查條件,避免虛假喚醒
while (!condition) {
wait(); // 釋放鎖并等待
}
// 條件滿足,執(zhí)行后續(xù)操作
doSomething();
}
public synchronized void signalCondition() {
condition = true;
notifyAll(); // 通知所有等待線程
}
}

wait/notify的使用要點:

  必須在同步方法或同步塊中調(diào)用。

  總是使用while循環(huán)檢查條件,避免虛假喚醒。

  優(yōu)先使用notifyAll()而不是notify(),避免信號丟失。

Condition接口:更精確的線程控制

public class ConditionDemo {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
private boolean ready = false;
public void await() throws InterruptedException {
lock.lock();
try {
while (!ready) {
condition.await(); // 等待條件
}
} finally {
lock.unlock();
}
}
public void signal() {
lock.lock();
try {
ready = true;
condition.signal(); // 通知等待線程
} finally {
lock.unlock();
}
}
}

Condition的優(yōu)勢:

  一個鎖可以關(guān)聯(lián)多個Condition。

  支持更靈活的等待條件。

  可以精確喚醒特定類型的等待線程。

六、線程池的核心原理:池化技術(shù)的典范

線程池的架構(gòu)設(shè)計

線程池采用了生產(chǎn)者-消費者模式:

  生產(chǎn)者:提交任務(wù)的線程

  消費者:工作線程

  緩沖區(qū):工作隊列

public class ThreadPoolAnatomy {
// ThreadPoolExecutor的核心構(gòu)造參數(shù)
ThreadPoolExecutor executor = new ThreadPoolExecutor(
5, // 核心線程數(shù):池中保持的線程數(shù)量
10, // 最大線程數(shù):池中允許的最大線程數(shù)量
60L, // 保持時間:超出核心線程數(shù)的空閑線程存活時間
TimeUnit.SECONDS, // 時間單位
new LinkedBlockingQueue<>(100), // 工作隊列:存儲待執(zhí)行任務(wù)
Executors.defaultThreadFactory(), // 線程工廠:創(chuàng)建新線程
new ThreadPoolExecutor.AbortPolicy() // 拒絕策略:無法處理任務(wù)時的策略
);
}

任務(wù)執(zhí)行流程的深度解析

任務(wù)提交:調(diào)用execute()或submit()方法

核心線程檢查:如果當(dāng)前線程數(shù) < corePoolSize,創(chuàng)建新線程

隊列檢查:如果線程數(shù) ≥ corePoolSize,嘗試將任務(wù)放入隊列

最大線程檢查:如果隊列已滿且線程數(shù) < maximumPoolSize,創(chuàng)建新線程

拒絕策略:如果隊列已滿且線程數(shù) ≥ maximumPoolSize,執(zhí)行拒絕策略

這個流程的重要性在于:它決定了線程池的行為特性。理解這個流程有助于我們根據(jù)具體場景配置合適的參數(shù)。

拒絕策略的四種選擇

AbortPolicy(默認):拋出RejectedExecutionException。

CallerRunsPolicy:由調(diào)用者線程執(zhí)行任務(wù)。

DiscardPolicy:靜默丟棄任務(wù)。

DiscardOldestPolicy:丟棄隊列中最老的任務(wù),然后重試。

七、常見問題與最佳實踐:經(jīng)驗的結(jié)晶

死鎖:四大必要條件

死鎖的發(fā)生需要同時滿足四個條件:

  互斥條件:資源不能被共享

  持有并等待:線程持有資源并等待其他資源

  不可剝奪:資源只能由持有線程釋放

  循環(huán)等待:存在線程資源的循環(huán)等待鏈

預(yù)防死鎖的策略:

  按固定順序獲取鎖

  使用tryLock()帶有超時機制

  使用更高級的并發(fā)工具

public class DeadlockPrevention {
private final Object lock1 = new Object();
private final Object lock2 = new Object();
public void method1() {
synchronized(lock1) {
// 一些操作
synchronized(lock2) {
// 臨界區(qū)
}
}
}
public void method2() {
synchronized(lock1) { // 使用與method1相同的鎖順序
// 一些操作
synchronized(lock2) {
// 臨界區(qū)
}
}
}
}

上下文切換:看不見的性能殺手

上下文切換的成本包括:

  直接成本:保存和恢復(fù)線程上下文。

  間接成本:緩存失效、TLB刷新。

優(yōu)化建議:

  避免創(chuàng)建過多線程。

  使用線程池復(fù)用線程。

  減少鎖競爭(鎖細化、使用并發(fā)集合)。

最佳實踐總結(jié)

命名線程:便于調(diào)試和監(jiān)控

ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
.setNameFormat("worker-thread-%d")
.build();

正確處理異常:

executor.submit(() -> {
try {
// 任務(wù)邏輯
} catch (Exception e) {
// 記錄日志,不要吞掉異常
logger.error("Task execution failed", e);
}
});

資源清理:

executor.shutdown();
try {
if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
executor.shutdownNow();
}
} catch (InterruptedException e) {
executor.shutdownNow();
Thread.currentThread().interrupt();
}

八、Java內(nèi)存模型(JMM):并發(fā)編程的理論基礎(chǔ)

happens-before關(guān)系

happens-before是JMM的核心概念,它定義了操作之間的可見性關(guān)系:

  程序次序規(guī)則:線程內(nèi)按照代碼順序執(zhí)行。

  監(jiān)視器鎖規(guī)則:解鎖操作happens-before后續(xù)的加鎖操作。

  volatile變量規(guī)則:寫操作happens-before后續(xù)的讀操作。

  線程啟動規(guī)則:Thread.start()happens-before線程內(nèi)的任何操作。

  線程終止規(guī)則:線程中的所有操作happens-before其他線程檢測到該線程已經(jīng)終止。

內(nèi)存屏障

為了實現(xiàn)happens-before關(guān)系,JVM在適當(dāng)?shù)奈恢貌迦雰?nèi)存屏障:

  LoadLoad屏障:禁止讀操作重排序。

  StoreStore屏障:禁止寫操作重排序。

  LoadStore屏障:禁止讀后寫重排序。

  StoreLoad屏障:禁止寫后讀重排序。

理解這些底層機制有助于我們寫出正確性更高的并發(fā)代碼。

到此這篇關(guān)于深入理解Java線程的文章就介紹到這了,更多相關(guān)java多線程內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springboot實現(xiàn)配置多環(huán)境yml方式

    springboot實現(xiàn)配置多環(huán)境yml方式

    在SpringBoot項目中,通過創(chuàng)建不同的YAML配置文件來實現(xiàn)多環(huán)境配置是一種常見且有效的方法,這些配置文件包括application.yml、application-dev.yml、application-prod.yml等,分別對應(yīng)不同的開發(fā)環(huán)境,如開發(fā)環(huán)境、生產(chǎn)環(huán)境
    2024-11-11
  • java設(shè)計模式-組合模式詳解

    java設(shè)計模式-組合模式詳解

    這篇文章主要介紹了JAVA設(shè)計模式之組合模式,簡單說明了組合模式的原理,并結(jié)合實例分析了java組合模式的具體用法,需要的朋友可以參考下
    2021-07-07
  • 5個主流的Java開源IDE工具詳解

    5個主流的Java開源IDE工具詳解

    這篇文章主要介紹了5個主流的Java開源IDE工具,無論如何,Java在當(dāng)今使用的編程語言中始終排在前三名,在TIOBE索引中涉及700萬到1000萬的程序員和開發(fā)者
    2020-07-07
  • SpringBoot+RabbitMQ方式收發(fā)消息的實現(xiàn)示例

    SpringBoot+RabbitMQ方式收發(fā)消息的實現(xiàn)示例

    這篇文章主要介紹了SpringBoot+RabbitMQ方式收發(fā)消息的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • @CacheEvict中的allEntries與beforeInvocation的區(qū)別說明

    @CacheEvict中的allEntries與beforeInvocation的區(qū)別說明

    這篇文章主要介紹了@CacheEvict中的allEntries與beforeInvocation的區(qū)別說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java圖形用戶界面之列表框

    Java圖形用戶界面之列表框

    列表框通過Swing組件JList產(chǎn)生,其總是在屏幕上占據(jù)固定行數(shù)的空間。這篇文章主要介紹了java圖形用戶界面之列表框的相關(guān)資料,非常不錯具有參考借鑒價值,需要的朋友可以參考下
    2016-10-10
  • spring cloud gateway請求跨域問題解決方案

    spring cloud gateway請求跨域問題解決方案

    這篇文章主要介紹了spring cloud gateway請求跨域問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • Java日常練習(xí)題,每天進步一點點(50)

    Java日常練習(xí)題,每天進步一點點(50)

    下面小編就為大家?guī)硪黄狫ava基礎(chǔ)的幾道練習(xí)題(分享)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-08-08
  • JAVA8 STREAM COLLECT GROUPBY分組實例解析

    JAVA8 STREAM COLLECT GROUPBY分組實例解析

    這篇文章主要介紹了JAVA8 STREAM COLLECT GROUPBY分組實例解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-01-01
  • MyBatis-Plus配置未生效的問題及解決

    MyBatis-Plus配置未生效的問題及解決

    本文主要探討了在使用MyBatis-Plus進行數(shù)據(jù)庫操作時遇到的問題,包括SQL語句未生效、Mapper接口未掃描、屬性未注入、Bean未注冊等問題,通過分析SpringBoot的配置類加載機制,本文提出了兩種解決方案:添加@Configuration注解和使用AutoConfiguration.imports文件
    2025-12-12

最新評論

巨野县| 沧州市| 得荣县| 桂阳县| 岳阳县| 云林县| 徐汇区| 托克托县| 鸡东县| 如皋市| 称多县| 三亚市| 茂名市| 吉首市| 汤原县| 临颍县| 连山| 西峡县| 佛坪县| 河北区| 苍山县| 霞浦县| 竹山县| 广灵县| 秦皇岛市| 随州市| 新绛县| 永济市| 中宁县| 高台县| 兴山县| 扶余县| 富蕴县| 开江县| 丹江口市| 延安市| 班戈县| 涟水县| 寻乌县| 大余县| 呼玛县|