class MyThread extends Thread {
private static int idGen = 0;
public MyThread() {
super("Thread-" + (++idGen)); // 設置線程名
}
@Override
public void run() {
System.out.println(getName() + " 正在運行");
}
}
public class Test {
public static void main(String[] args) {
new MyThread().start(); // 必須調用 start(),不能調用 run()
new MyThread().start();
}
}
關鍵點:start() 啟動新線程並調用 run();直接調用 run() 只是主線程執行普通方法。
class MyTask implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 執行任務");
}
}
public class Test {
public static void main(String[] args) {
Thread t1 = new Thread(new MyTask(), "Worker-1");
Thread t2 = new Thread(new MyTask(), "Worker-2");
t1.start(); t2.start();
}
}
優勢:避免單繼承限制,任務與線程分離,配合線程池更靈活。
| 方法 | 說明 |
|---|---|
| start() | 啟動線程 |
| join() | 等待該線程終止 |
| sleep(ms) | 當前線程休眠 |
| setDaemon(true) | 設置守護線程 (JVM 退出不等待) |
| interrupt() | 中斷線程 |
| currentThread() | 獲取當前線程 |
多線程共享堆內存對象,並發修改導致競態條件:結果依賴執行時序。
class Counter {
private int count = 0;
public synchronized void increment() { // 實例鎖:this
count++;
}
public static synchronized void staticIncrement() { // 類鎖:Counter.class
// ...
}
}
public void increment() {
synchronized (this) { // 也可用其他對象作為鎖
count++;
}
}
class TicketPool { // 共享資源
private int tickets = 100;
public synchronized boolean sell() { // 同步方法:原子化「判斷+出票」
if (tickets > 0) {
tickets--;
System.out.println(Thread.currentThread().getName() + " 賣出第 " + (100-tickets) + " 張");
return true;
}
return false;
}
}
class Seller extends Thread {
private TicketPool pool;
private int sold = 0;
public Seller(TicketPool pool) { this.pool = pool; }
@Override
public void run() {
while (pool.sell()) {
sold++;
try { Thread.sleep((int)(Math.random() * 100)); } catch (InterruptedException e) {}
}
System.out.println(getName() + " 共賣出 " + sold + " 張");
}
}
public class Test {
public static void main(String[] args) {
TicketPool pool = new TicketPool();
new Seller(pool).start();
new Seller(pool).start();
new Seller(pool).start();
}
}
輸出保證:無超賣、無重賣、總數正好 100 張。
synchronized 方法/塊 = 獲取鎖 → 執行 → 釋放鎖static synchronized 鎖住 Class 對象
// 粗粒度鎖:整個方法同步,並發度低
public synchronized void process() { ... }
// 細粒度鎖:僅同步核心邏輯
public void process() {
// 非共享操作...
synchronized (sharedResource) {
// 共享資源核心操作
}
// 非共享操作...
}
原則:同步塊越小越好,但不可破壞原子性邊界。
| 特性 | 含義 | synchronized 支持 |
|---|---|---|
| 原子性 | 操作不可分割 | ✓ (鎖保證) |
| 可見性 | 修改對其他線程立即可見 | ✓ (刷新主內存) |
| 有序性 | 禁止指令重排序 | ✓ (happens-before) |
synchronized (new Object()) 每次新對象,失效synchronized ("lock") 常量池共享,意外阻塞if (!map.containsKey(k)) map.put(k,v) 需整體同步ReentrantLock、ReadWriteLock,支持公平鎖、可中斷、超時ConcurrentHashMap、CopyOnWriteArrayList、BlockingQueueAtomicInteger、LongAdder,CAS 無鎖ExecutorService,統一管理線程生命周期多線程核心在於共享資源的協調。synchronized 是 Java 最基礎的同步機制,通過對象監視器實現互斥訪問。理解「線程 vs 任務」、「鎖對象選擇」、「同步粒度」、「happens-before 規則」是寫出正確高效併發代碼的基石。現代開發應優先使用高級併發工具,但 synchronized 仍是底層基石,且在 JVM 優化 (偏向鎖、輕量級鎖、重量級鎖升級) 下性能優異。