一、基礎(chǔ)概念
1.進程與線程
進程:操作系統(tǒng)資源分配的基本單位,擁有獨立的內(nèi)存空間(如代碼段、堆、方法區(qū))。
線程:進程內(nèi)的執(zhí)行單元,是CPU調(diào)度的最小單位,共享進程資源(如堆內(nèi)存),但擁有獨立的棧空間。
單線程 vs 多線程:單線程按順序執(zhí)行任務(wù),多線程通過并發(fā)/并行提升性能(需多核CPU支持并行)。
2.并發(fā)與并行
并發(fā):單核CPU通過時間片輪轉(zhuǎn)模擬多任務(wù)交替執(zhí)行。
并行:多核CPU同時執(zhí)行多個任務(wù)。
二、線程的創(chuàng)建與啟動
Java提供兩種核心方式創(chuàng)建線程:
1.繼承Thread類
class MyThread extends Thread {
? ? @Override
? ? public void run() {
? ? ? ? System.out.println("線程執(zhí)行中:" + Thread.currentThread().getName());
? ? }
}
// 啟動線程
public static void main(String[] args) {
? ? MyThread t = new MyThread();
? ? t.start();? // 啟動新線程
}
特點:簡單但受限于單繼承。
2.實現(xiàn)Runnable接口
class MyRunnable implements Runnable {
? ? @Override
? ? public void run() {
? ? ? ? System.out.println("任務(wù)執(zhí)行中:" + Thread.currentThread().getName());
? ? }
}
// 啟動線程
public static void main(String[] args) {
? ? Thread t = new Thread(new MyRunnable());
? ? t.start();
}
優(yōu)勢:避免單繼承限制,支持資源共享。
3.其他方式
Lambda表達式(Java 8+):簡化代碼,如?new Thread(() -> System.out.println("Lambda線程")).start();
Callable接口:支持返回值和異常處理,需配合Future使用。
三、線程生命周期與狀態(tài)
線程狀態(tài)包括:
NEW(新建) → RUNNABLE(就緒) → RUNNING(運行) → BLOCKED(阻塞) → WAITING(等待) → TIMED_WAITING(計時等待) → TERMINATED(終止)。
關(guān)鍵方法:
join():等待線程結(jié)束(如主線程等待子線程完成)。
setPriority():設(shè)置優(yōu)先級(1-10,默認5)。
sleep():暫停線程執(zhí)行(單位:毫秒)。
setDaemon(true):設(shè)為守護線程(主線程退出時自動終止)。
四、線程同步與并發(fā)安全
多線程共享資源時需解決數(shù)據(jù)競爭問題:
1.同步代碼塊
synchronized (lockObject) {
? ? // 臨界區(qū)代碼
}
原理:基于對象監(jiān)視器鎖(Monitor Lock),確保同一時間僅一個線程訪問臨界區(qū)。
2.同步方法
public synchronized void method() {
? ? // 同步方法體
}
等價于:synchronized (this)。
3.Lock接口
ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
? ? // 臨界區(qū)操作
} finally {
? ? lock.unlock();? // 必須釋放鎖
}
優(yōu)勢:支持公平鎖、可中斷鎖等高級特性。
4.原子類
AtomicInteger counter = new AtomicInteger(0);
int value = counter.incrementAndGet();? // 原子遞增
原理:基于CAS(Compare-And-Swap)實現(xiàn)無鎖并發(fā)。
五、線程池技術(shù)
作用:復(fù)用線程,減少創(chuàng)建/銷毀開銷,提升性能。
1.核心參數(shù)
corePoolSize:核心線程數(shù)(常駐)。
maximumPoolSize:最大線程數(shù)。
workQueue:任務(wù)隊列(如LinkedBlockingQueue)。
RejectedExecutionHandler:拒絕策略(如丟棄、拋異常)。
2.創(chuàng)建線程池
ExecutorService executor = Executors.newFixedThreadPool(5); // 固定線程池
executor.submit(() -> System.out.println("任務(wù)提交"));
executor.shutdown();? // 優(yōu)雅關(guān)閉
3.線程池類型
FixedThreadPool:固定線程數(shù)。
CachedThreadPool:彈性線程池(自動回收空閑線程)。
ScheduledThreadPool:支持定時任務(wù)。
六、高級并發(fā)工具
1.CountDownLatch
CountDownLatch latch = new CountDownLatch(3);
// 等待3個線程完成
latch.await();
用途:主線程等待多個子線程完成。
2.CyclicBarrier
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("所有線程就緒"));
// 多個線程相互等待后同步執(zhí)行
barrier.await();
用途:多線程協(xié)同執(zhí)行任務(wù)。
3.ConcurrentHashMap
線程安全哈希表,通過分段鎖(JDK 1.7)或CAS(JDK 1.8)實現(xiàn)高并發(fā)性能。
七、注意事項
避免死鎖:按固定順序獲取鎖,或使用tryLock()超時機制。
線程中斷:通過interrupt()方法中斷線程,需配合狀態(tài)檢查(如isInterrupted())。
資源競爭:減少鎖粒度,優(yōu)先使用無鎖數(shù)據(jù)結(jié)構(gòu)(如ConcurrentLinkedQueue)。
示例:多線程售票系統(tǒng)
class TicketSystem implements Runnable {
? ? private int tickets = 100;
? ? private final Object lock = new Object();
? ? @Override
? ? public void run() {
? ? ? ? while (true) {
? ? ? ? ? ? synchronized (lock) {
? ? ? ? ? ? ? ? if (tickets <= 0) break;
? ? ? ? ? ? ? ? System.out.println(Thread.currentThread().getName() + "售出第" + tickets--);
? ? ? ? ? ? }
? ? ? ? ? ? try {
? ? ? ? ? ? ? ? Thread.sleep(100);? // 模擬售票耗時
? ? ? ? ? ? } catch (InterruptedException e) {
? ? ? ? ? ? ? ? e.printStackTrace();
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
public class Main {
? ? public static void main(String[] args) {
? ? ? ? Thread t1 = new Thread(new TicketSystem(), "窗口1");
? ? ? ? Thread t2 = new Thread(new TicketSystem(), "窗口2");
? ? ? ? t1.start();
? ? ? ? t2.start();
? ? }
}
輸出:多個線程交替售出票號,保證數(shù)據(jù)一致性。
通過合理使用線程創(chuàng)建、同步機制和并發(fā)工具,Java多線程編程可顯著提升程序性能,但需謹慎處理資源競爭與線程安全問題。