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

Java 多線程基礎入門:創建方式、生命周期、同步機制、鎖優化、單例模式與死鎖避坑

     編輯:Java 綜合教學

核心概念

  • 進程:運行中的程序,擁有獨立內存空間,至少包含一個線程
  • 線程:進程內的執行單元,共享進程內存,獨立棧、程序計數器
  • JVM 啟動 → main 線程(主線程)+ GC 線程 + 其他守護線程

多線程創建兩種方式

方式一:繼承 Thread 類

public class MyThread extends Thread {
    @Override public void run() {
        for (int i = 0; i < 60; i++) 
            System.out.println(getName() + " run " + i);
    }
}

public class Demo {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start();  // 啟動線程,調用 run()
        // t.run(); // 直接調用,不啟動新線程!
        for (int i = 0; i < 60; i++) 
            System.out.println("main " + i);
    }
}

方式二:實現 Runnable 接口(推薦)

public class Ticket implements Runnable {
    private static int tick = 100;
    private final Object lock = new Object();
    
    public void run() {
        while (true) {
            synchronized (lock) {  // 同步代碼塊
                if (tick > 0) 
                    System.out.println(Thread.currentThread().getName() + ":" + tick--);
                else 
                    return;
            }
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        Ticket task = new Ticket();
        new Thread(task, "窗口A").start();
        new Thread(task, "窗口B").start();
        new Thread(task, "窗口C").start();
    }
}

差異對比

維度繼承 Thread實現 Runnable
繼承限制單繼承無限制
代碼復用差好(同任務多線程)
線程對象thisnew Thread(runnable)
推薦度低高

線程常用操作

  • start():啟動線程(異步)
  • run():普通方法調用(同步)
  • Thread.currentThread():獲取當前線程對象
  • getName()/setName():獲取/設置線程名
  • sleep(ms):靜態方法,當前線程休眠,不釋放鎖
  • join():等待該線程終止

線程生命周期狀態

NEW → RUNNABLE → BLOCKED/WAITING/TIMED_WAITING → TERMINATED
  • sleep()/wait() → 進入阻塞/等待
  • notify()/notifyAll() → 喚醒
  • 搶佔 CPU 失敗 → 就緒態

線程安全與同步機制

問題根源

多線程操作共享數據,非原子操作被打斷 → 數據不一致。

解決方案一:同步代碼塊

synchronized(lockObject) {
    // 臨界區:操作共享數據
}
  • 鎖對象:任意對象,多線程必須共用同一把鎖
  • 持有鎖才能進入,其他線程阻塞等待

解決方案二:同步方法

public synchronized void add(int n) { ... }  // 鎖 this
public static synchronized void staticAdd() { ... } // 鎖 Class 對象

解決方案三:JDK 5+ Lock 介面

Lock lock = new ReentrantLock();
lock.lock();
try { ... } finally { lock.unlock(); }

單例模式與線程安全

餓漢式(類加載時創建,天然線程安全)

public class Singleton {
    private static final Singleton INSTANCE = new Singleton();
    private Singleton() {}
    public static Singleton getInstance() { return INSTANCE; }
}

懶漢式雙重檢查鎖(DCL)


public class Singleton {
    private static volatile Singleton instance; // volatile 禁止指令重排
    private Singleton() {}
    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null)
                    instance = new Singleton();
            }
        }
        return instance;
    }
}

死鎖經典案例與避免


public class DeadLockDemo {
    static Object lockA = new Object();
    static Object lockB = new Object();
    
    public static void main(String[] args) {
        new Thread(() -> {
            synchronized (lockA) {
                sleep(10);
                synchronized (lockB) { System.out.println("A->B"); }
            }
        }).start();
        new Thread(() -> {
            synchronized (lockB) {
                sleep(10);
                synchronized (lockA) { System.out.println("B->A"); }
            }
        }).start();
    }
}

避免原則

  • 固定鎖獲取順序(如按 System.identityHashCode 排序)
  • 使用 tryLock(timeout) 避免無限等待
  • 減少鎖持有時間、避免嵌套鎖

總結

掌握 Runnable + Thread 創建、synchronized/Lock 同步、volatile 可見性、DCL 單例、死鎖預防,是 Java 併發編程的必修課。實戰中優先使用 java.util.concurrent 高級工具(線程池、並發集合、同步器)。

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