首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 線程編程核心:Thread 類、Runnable、Callable、Future 與線程池完整指南

     編輯:Java 相關知識

線程創建的三種標準方式

1. 繼承 Thread 類 (不推薦,繼承耦合)


class MyThread extends Thread {
    @Override public void run() {
        System.out.println("Thread: " + getName() + " running");
    }
}
new MyThread().start(); // 必須調用 start(),而非 run()

2. 實現 Runnable 接口 (推薦,分離任務與執行)


class MyTask implements Runnable {
    @Override public void run() {
        System.out.println("Runnable: " + Thread.currentThread().getName());
    }
}
new Thread(new MyTask()).start();
// 或線程池執行
executor.execute(new MyTask());

3. 實現 Callable + FutureTask (有返回值、可拋異常)


import java.util.concurrent.*;

class MyCallable implements Callable {
    @Override public Integer call() throws Exception {
        Thread.sleep(1000);
        return 42; // 返回結果
    }
}

// 用法
ExecutorService es = Executors.newSingleThreadExecutor();
Future future = es.submit(new MyCallable());
Integer result = future.get(); // 阻塞獲取結果
es.shutdown();

Thread 核心 API 速查表

方法作用注意
start()啟動線程,JVM 調用 run()只能調用一次,否則 IllegalThreadStateException
run()線程執行體直接調用不會啟動新線程,只是普通方法調用
sleep(ms)當前線程休眠 (靜態)不釋放鎖,拋 InterruptedException
yield()當前線程讓出 CPU (靜態)僅重新參與調度,不保證切換
join()等待該線程終止常用於主線程等待子線程
interrupt()設置中斷標誌位不會強制停止,需代碼配合檢查
isInterrupted()檢查中斷標誌 (不清除)靜態 interrupted() 會清除標誌
setDaemon(true)設置守護線程需在 start() 前調用;JVM 只有守護線程時退出
setName()/getName()設置/獲取線程名調試、日誌追蹤關鍵
getId()獲取唯一線程 ID (long)JVM 分配,不重複
getState()獲取線程狀態枚舉NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
setPriority(int)設置優先級 1-10僅提示調度器,不可靠
currentThread()獲取當前執行線程 (靜態)最常用獲取上下文方式

線程生命周期狀態轉換

NEW --start()--> RUNNABLE (就緒/運行) 
RUNNABLE --sleep/wait/join/IO--> TIMED_WAITING / WAITING / BLOCKED
TIMED_WAITING / WAITING / BLOCKED --超時/通知/獲取鎖--> RUNNABLE
RUNNABLE --run() 結束/拋出未捕獲異常--> TERMINATED

線程安全基礎:synchronized、volatile、ThreadLocal

synchronized (內置鎖)


// 同步方法 (鎖 this / Class 對象)
public synchronized void safeMethod() { }

// 同步代碼塊 (指定鎖對象)
public void safeBlock() {
    synchronized (lockObject) { // lockObject 必須非 null、共享、不可變
        // 臨界區
    }
}

volatile (可見性、有序性、不保證原子性)


class VolatileDemo {
    volatile boolean flag = false; // 寫入立即刷新主存,讀取立即從主存
    volatile long counter = 0;     // long/double 64位讀寫非原子,volatile 保證原子讀寫
    
    void writer() { flag = true; counter++; }
    void reader() { if (flag) System.out.println(counter); }
}

ThreadLocal (線程封閉,空間換時間)


class ThreadLocalDemo {
    // 每個線程獨立副本,互不干擾
    static final ThreadLocal formatter = 
        ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    
    static String format(Date date) {
        return formatter.get().format(date); // 線程安全,無鎖
    }
    
    // 記得清理 (線程池場景必須)
    static void clean() { formatter.remove(); }
}

線程池:ExecutorService 核心參數與最佳實踐

ThreadPoolExecutor 七大參數


new ThreadPoolExecutor(
    corePoolSize,      // 核心線程數 (常駐)
    maximumPoolSize,   // 最大線程數 (峰值)
    keepAliveTime,     // 非核心線程空閒存活時間
    TimeUnit.SECONDS,  // 時間單位
    workQueue,         // 任務隊列 (關鍵!)
    threadFactory,     // 線程工廠 (命名、守護、優先級)
    handler            // 拒絕策略 (隊列滿、線程數達最大時)
);

四大內置隊列選型指南

隊列特點適用場景風險
ArrayBlockingQueue有界數組固定緩衝、需控制內存需預估容量
LinkedBlockingQueue無界鏈表 (默認 Integer.MAX_VALUE)一般業務、吞吐優先OOM 風險 (任務產生 > 消費)
SynchronousQueue零容量、直接移交高併發、快速任務、CachedThreadPool任務積壓直接拒絕/新建線程
DelayQueue延遲執行 (定時任務)ScheduledThreadPoolExecutor特定場景

四大拒絕策略

  • AbortPolicy (默認):拋 RejectedExecutionException
  • CallerRunsPolicy:調用者線程執行任務 (降速回壓)
  • DiscardPolicy:靜默丟棄新任務
  • DiscardOldestPolicy:丟棄隊列最舊任務,嘗試重新提交

Executors 工廠方法陷阱 (阿里規約禁用)

方法內部實現風險
newFixedThreadPoolLinkedBlockingQueue 無界任務堆積 OOM
newSingleThreadExecutorLinkedBlockingQueue 無界任務堆積 OOM
newCachedThreadPoolSynchronousQueue + 無限線程線程爆炸 OOM
newScheduledThreadPoolDelayedWorkQueue 無界任務堆積 OOM

生產環境推薦:自定義線程池


import java.util.concurrent.*;

public class ThreadPoolConfig {
    public static ExecutorService createBusinessPool() {
        return new ThreadPoolExecutor(
            8,                      // core: CPU 密集型 = 核心數; IO 密集型 = 2*核心數
            16,                     // max: 峰值緩衝
            60, TimeUnit.SECONDS,   // keepAlive
            new ArrayBlockingQueue<>(2000), // 有界隊列,防 OOM
            new ThreadFactoryBuilder()
                .setNameFormat("biz-worker-%d") // 關鍵:有意義名稱
                .setDaemon(false)
                .build(),
            new ThreadPoolExecutor.CallerRunsPolicy() // 回壓,保護系統
        );
    }
    
    // 優雅關閉模板
    public static void shutdown(ExecutorService pool, String name) {
        pool.shutdown(); // 不再接受新任務
        try {
            if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
                List remaining = pool.shutdownNow(); // 強制中斷
                log.warn("{} 強制關閉,剩餘任務: {}", name, remaining.size());
            }
        } catch (InterruptedException e) {
            pool.shutdownNow();
            Thread.currentThread().interrupt();
        }
    }
}

CompletableFuture:異步編排利器 (JDK 8+)


ExecutorService es = ThreadPoolConfig.createBusinessPool();

// 1. 供給型異步任務
CompletableFuture cf1 = CompletableFuture.supplyAsync(() -> {
    return "Hello";
}, es);

// 2. 消費型回調
cf1.thenAccept(s -> System.out.println("收到: " + s));

// 3. 轉換鏈
CompletableFuture cf2 = cf1.thenApply(String::length);

// 4. 組合多個 Future
CompletableFuture cf3 = CompletableFuture.supplyAsync(() -> "World", es);
CompletableFuture combined = cf1.thenCombine(cf3, (a, b) -> a + " " + b);

// 5. 異常處理
combined.exceptionally(ex -> {
    log.error("異步鏈出錯", ex);
    return "Default";
});

// 6. 等待所有完成
CompletableFuture.allOf(cf1, cf2, cf3).join();

es.shutdown();

總結

Java 線程編程核心在於:任務與執行分離 (Runnable/Callable)、線程池管理資源 (有界隊列、拒絕策略、命名)、同步工具選型 (synchronized/volatile/Lock/並發集合)、異步編排 (CompletableFuture)。牢記:禁止直接使用 Executors 默認工廠、線程池必須有界、守護線程慎用、中斷協作而非強制停止、ThreadLocal 線程池場景必須清理。掌握這些,即可構建高併發、穩定、可維護的多線程系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved