12-Java语言核心-并发编程-线程基础详解

2 阅读14分钟

线程基础详解

一、知识概述

线程是Java并发编程的基础单元。理解线程的生命周期、创建方式、调度机制和基本操作,是掌握Java并发编程的第一步。本文将深入讲解线程的核心概念和实践技巧。

线程概览

┌─────────────────────────────────────────────────────────────────────┐
│                      Java线程体系                                    │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  ┌─────────────────────────────────────────────────────────────┐   │
│  │                    Thread 类层次                             │   │
│  ├─────────────────────────────────────────────────────────────┤   │
│  │                                                             │   │
│  │  java.lang.Thread                                           │   │
│  │       ├── 继承Thread创建线程                                 │   │
│  │       └── 实现Runnable接口创建线程                           │   │
│  │                                                             │   │
│  │  java.util.concurrent                                       │   │
│  │       ├── ExecutorService (线程池)                          │   │
│  │       ├── Future<T> (异步结果)                              │   │
│  │       ├── Callable<V> (可返回任务)                          │   │
│  │       └── CompletableFuture (异步编排)                      │   │
│  │                                                             │   │
│  └─────────────────────────────────────────────────────────────┘   │
│                                                                     │
│  线程状态转换:                                                      │
│  ┌──────┐   start()   ┌─────────┐                                  │
│  │ NEW  │───────────►│ RUNNABLE │◄────────┐                       │
│  └──────┘            └────┬────┘         │                       │
│                           │              │                       │
│            ┌──────────────┼──────────────┤                       │
│            ▼              ▼              ▼                       │
│     ┌─────────┐   ┌─────────┐   ┌──────────────┐                 │
│     │ BLOCKED │   │ WAITING │   │TIMED_WAITING │                 │
│     └────┬────┘   └────┬────┘   └──────┬───────┘                 │
│          │              │              │                         │
│          └──────────────┴──────────────┘                         │
│                         │                                        │
│                         ▼                                        │
│                   ┌───────────┐                                  │
│                   │TERMINATED │                                  │
│                   └───────────┘                                  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

进程与线程

特性进程线程
定义资源分配的基本单位CPU调度的基本单位
内存独立地址空间共享进程内存
通信IPC(管道、消息队列等)直接读写共享变量
开销创建/切换开销大创建/切换开销小
稳定性进程间相互隔离一个线程崩溃可能影响整个进程

二、知识点详细讲解

2.1 线程的创建

2.1.1 三种创建方式
/**
 * 线程创建的三种方式
 */
public class ThreadCreationDemo {
    
    public static void main(String[] args) {
        System.out.println("=== 线程创建方式 ===\n");
        
        // 方式1:继承Thread类
        class MyThread extends Thread {
            @Override
            public void run() {
                System.out.println("方式1: 继承Thread类 - " + Thread.currentThread().getName());
            }
        }
        
        // 方式2:实现Runnable接口
        class MyRunnable implements Runnable {
            @Override
            public void run() {
                System.out.println("方式2: 实现Runnable接口 - " + Thread.currentThread().getName());
            }
        }
        
        // 方式3:实现Callable接口(可返回结果)
        class MyCallable implements java.util.concurrent.Callable<String> {
            @Override
            public String call() throws Exception {
                Thread.sleep(100);
                return "方式3: 实现Callable接口 - " + Thread.currentThread().getName();
            }
        }
        
        // 启动方式1
        Thread thread1 = new MyThread();
        thread1.start();
        
        // 启动方式2
        Thread thread2 = new Thread(new MyRunnable());
        thread2.start();
        
        // 使用Lambda简化方式2
        Thread thread2Lambda = new Thread(() -> {
            System.out.println("方式2(Lambda): " + Thread.currentThread().getName());
        });
        thread2Lambda.start();
        
        // 启动方式3
        java.util.concurrent.ExecutorService executor = 
            java.util.concurrent.Executors.newSingleThreadExecutor();
        java.util.concurrent.Future<String> future = executor.submit(new MyCallable());
        try {
            System.out.println(future.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
        executor.shutdown();
        
        // 对比三种方式
        compareCreationMethods();
    }
    
    private static void compareCreationMethods() {
        System.out.println("\n【三种创建方式对比】\n");
        
        System.out.println("┌─────────────────┬─────────────────┬─────────────────┐");
        System.out.println("│ 方式            │ 优点            │ 缺点            │");
        System.out.println("├─────────────────┼─────────────────┼─────────────────┤");
        System.out.println("│ 继承Thread      │ 简单直接        │ 不支持多继承    │");
        System.out.println("├─────────────────┼─────────────────┼─────────────────┤");
        System.out.println("│ 实现Runnable    │ 支持多继承      │ 无返回值        │");
        System.out.println("│                 │ 资源共享        │                 │");
        System.out.println("├─────────────────┼─────────────────┼─────────────────┤");
        System.out.println("│ 实现Callable    │ 有返回值        │ 使用稍复杂      │");
        System.out.println("│                 │ 可抛异常        │                 │");
        System.out.println("└─────────────────┴─────────────────┴─────────────────┘");
        System.out.println();
        
        System.out.println("推荐使用:");
        System.out.println("  1. 优先使用实现Runnable/Callable接口");
        System.out.println("  2. 配合线程池使用");
        System.out.println("  3. 避免直接继承Thread类");
        System.out.println();
    }
}
2.1.2 Thread类构造方法
/**
 * Thread类构造方法详解
 */
public class ThreadConstructorDemo {
    
    public static void main(String[] args) {
        System.out.println("=== Thread构造方法 ===\n");
        
        /*
        Thread构造方法:
        
        1. Thread()                        // 无参构造
        2. Thread(Runnable target)         // 指定任务
        3. Thread(String name)             // 指定线程名
        4. Thread(Runnable target, String name)  // 任务+名字
        5. Thread(ThreadGroup group, Runnable target)  // 指定线程组
        6. Thread(ThreadGroup group, String name)
        7. Thread(ThreadGroup group, Runnable target, String name)
        8. Thread(ThreadGroup group, Runnable target, String name, long stackSize)
        */
        
        System.out.println("常用构造方法:");
        System.out.println();
        
        // 1. 无参构造
        Thread t1 = new Thread();
        System.out.println("无参构造: " + t1.getName()); // Thread-0
        
        // 2. 指定任务
        Thread t2 = new Thread(() -> System.out.println("执行任务"));
        System.out.println("指定任务: " + t2.getName()); // Thread-1
        
        // 3. 指定名字
        Thread t3 = new Thread("my-thread");
        System.out.println("指定名字: " + t3.getName()); // my-thread
        
        // 4. 任务+名字
        Thread t4 = new Thread(() -> {}, "worker-thread");
        System.out.println("任务+名字: " + t4.getName()); // worker-thread
        
        // 5. 指定线程组
        ThreadGroup group = new ThreadGroup("my-group");
        Thread t5 = new Thread(group, () -> {}, "group-thread");
        System.out.println("线程组: " + t5.getThreadGroup().getName()); // my-group
        
        // 6. 指定栈大小(不推荐使用)
        Thread t6 = new Thread(null, () -> {}, "big-stack-thread", 1024 * 1024);
        System.out.println("指定栈大小: " + t6.getName());
        
        System.out.println();
        System.out.println("命名规范:");
        System.out.println("  - 使用有意义的名称,便于调试");
        System.out.println("  - 例如: pool-1-thread-1, worker-1, producer, consumer");
        System.out.println("  - 可使用ThreadFactory定制命名");
        System.out.println();
    }
}

2.2 线程的生命周期

2.2.1 线程状态
/**
 * 线程生命周期详解
 */
public class ThreadLifecycleDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 线程生命周期 ===\n");
        
        demonstrateStates();
        stateTransitions();
    }
    
    private static void demonstrateStates() throws InterruptedException {
        System.out.println("【线程状态演示】\n");
        
        // NEW: 新建状态
        Thread thread = new Thread(() -> {
            try {
                // RUNNABLE: 运行状态(包括就绪和运行中)
                System.out.println("状态: " + Thread.currentThread().getState());
                
                // TIMED_WAITING: 超时等待
                Thread.sleep(100);
                
                // WAITING: 等待状态
                synchronized (ThreadLifecycleDemo.class) {
                    ThreadLifecycleDemo.class.wait(50);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        System.out.println("创建后状态: " + thread.getState()); // NEW
        
        thread.start();
        System.out.println("启动后状态: " + thread.getState()); // RUNNABLE
        
        Thread.sleep(10); // 让线程开始执行
        
        // 等待线程结束
        thread.join();
        
        System.out.println("结束后状态: " + thread.getState()); // TERMINATED
        System.out.println();
    }
    
    private static void stateTransitions() {
        System.out.println("【状态转换详解】\n");
        
        System.out.println("1. NEW (新建)");
        System.out.println("   - 线程刚创建,尚未启动");
        System.out.println("   - 调用start()后变为RUNNABLE");
        System.out.println();
        
        System.out.println("2. RUNNABLE (可运行)");
        System.out.println("   - 包括就绪(Ready)和运行中(Running)");
        System.out.println("   - 可能正在执行,也可能等待CPU时间片");
        System.out.println();
        
        System.out.println("3. BLOCKED (阻塞)");
        System.out.println("   - 等待获取监视器锁");
        System.out.println("   - 进入synchronized块/方法");
        System.out.println("   - 获取锁后变为RUNNABLE");
        System.out.println();
        
        System.out.println("4. WAITING (等待)");
        System.out.println("   - 无限等待,需其他线程唤醒");
        System.out.println("   - 触发方法:");
        System.out.println("     - Object.wait()");
        System.out.println("     - Thread.join()");
        System.out.println("     - LockSupport.park()");
        System.out.println();
        
        System.out.println("5. TIMED_WAITING (超时等待)");
        System.out.println("   - 有时限的等待");
        System.out.println("   - 触发方法:");
        System.out.println("     - Thread.sleep(time)");
        System.out.println("     - Object.wait(time)");
        System.out.println("     - Thread.join(time)");
        System.out.println("     - LockSupport.parkNanos(time)");
        System.out.println();
        
        System.out.println("6. TERMINATED (终止)");
        System.out.println("   - 线程执行完毕");
        System.out.println("   - 或因异常退出");
        System.out.println();
        
        System.out.println("状态转换图:");
        System.out.println("""
              start()
        NEW ─────────► RUNNABLE ◄─────────────────────┐
                          │                          │
              ┌───────────┼───────────┐              │
              │           │           │              │
              ▼           ▼           ▼              │
         BLOCKED     WAITING    TIMED_WAITING        │
              │           │           │              │
              └───────────┴───────────┴──────────────┘
                          │
                          ▼
                    TERMINATED
        """);
        System.out.println();
    }
}

/**
 * 线程状态详细演示
 */
class ThreadStateDemo {
    
    private static final Object lock = new Object();
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 线程状态转换实例 ===\n");
        
        // BLOCKED状态演示
        demonstrateBlockedState();
        
        // WAITING状态演示
        demonstrateWaitingState();
        
        // TIMED_WAITING状态演示
        demonstrateTimedWaitingState();
    }
    
    private static void demonstrateBlockedState() throws InterruptedException {
        System.out.println("【BLOCKED状态演示】\n");
        
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(2000); // 持有锁2秒
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }, "Thread-1");
        
        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                // 尝试获取锁,但被t1持有
            }
        }, "Thread-2");
        
        t1.start();
        Thread.sleep(100); // 确保t1先获取锁
        t2.start();
        Thread.sleep(100); // 确保t2开始等待锁
        
        System.out.println(t2.getName() + " 状态: " + t2.getState()); // BLOCKED
        
        t1.join();
        t2.join();
        System.out.println();
    }
    
    private static void demonstrateWaitingState() throws InterruptedException {
        System.out.println("【WAITING状态演示】\n");
        
        Thread t = new Thread(() -> {
            synchronized (lock) {
                try {
                    lock.wait(); // 无限等待
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }, "Waiting-Thread");
        
        t.start();
        Thread.sleep(100);
        
        System.out.println(t.getName() + " 状态: " + t.getState()); // WAITING
        
        // 唤醒线程
        synchronized (lock) {
            lock.notify();
        }
        
        t.join();
        System.out.println();
    }
    
    private static void demonstrateTimedWaitingState() throws InterruptedException {
        System.out.println("【TIMED_WAITING状态演示】\n");
        
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(5000); // 睡眠5秒
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "Sleeping-Thread");
        
        t.start();
        Thread.sleep(100);
        
        System.out.println(t.getName() + " 状态: " + t.getState()); // TIMED_WAITING
        
        t.interrupt(); // 中断睡眠
        t.join();
        System.out.println();
    }
}

2.3 线程的基本操作

2.3.1 启动与停止
import java.util.concurrent.*;

/**
 * 线程启动与停止
 */
public class ThreadStartStopDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 线程启动与停止 ===\n");
        
        startMethod();
        stopMethod();
        interruptMethod();
    }
    
    private static void startMethod() {
        System.out.println("【start()方法】\n");
        
        /*
        start() vs run():
        
        - start(): 启动新线程,JVM调用run()方法
        - run(): 在当前线程中执行,不会创建新线程
        */
        
        Thread t1 = new Thread(() -> {
            System.out.println("执行线程: " + Thread.currentThread().getName());
        });
        
        // 正确方式
        t1.start();
        
        // 错误方式(不会创建新线程)
        // t1.run();  // 只是在当前线程调用方法
        
        System.out.println();
        System.out.println("注意事项:");
        System.out.println("  1. 一个线程只能启动一次");
        System.out.println("  2. 重复调用start()会抛出IllegalThreadStateException");
        System.out.println("  3. 不要直接调用run()方法");
        System.out.println();
    }
    
    private static void stopMethod() throws InterruptedException {
        System.out.println("【停止线程的正确方式】\n");
        
        System.out.println("❌ 已废弃的方法:");
        System.out.println("  - stop(): 强制停止,不安全");
        System.out.println("  - suspend(): 挂起线程,容易死锁");
        System.out.println("  - resume(): 恢复线程");
        System.out.println();
        
        System.out.println("✅ 正确的停止方式:");
        System.out.println("  1. 使用volatile标志位");
        System.out.println("  2. 使用interrupt()中断");
        System.out.println("  3. 使用Future.cancel()");
        System.out.println();
        
        // 方式1: volatile标志位
        class StoppableTask implements Runnable {
            private volatile boolean stopped = false;
            
            @Override
            public void run() {
                while (!stopped && !Thread.currentThread().isInterrupted()) {
                    // 执行任务
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        break;
                    }
                }
                System.out.println("线程正常停止");
            }
            
            public void stop() {
                stopped = true;
            }
        }
        
        StoppableTask task = new StoppableTask();
        Thread t = new Thread(task);
        t.start();
        
        Thread.sleep(500);
        task.stop(); // 正常停止
        t.join();
        
        System.out.println();
    }
    
    private static void interruptMethod() throws InterruptedException {
        System.out.println("【interrupt()机制】\n");
        
        // 演示中断机制
        Thread t = new Thread(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // sleep被中断会清除中断标志,需要重新设置
                    System.out.println("线程被中断");
                    Thread.currentThread().interrupt(); // 重新设置中断标志
                    break;
                }
            }
            System.out.println("线程响应中断并退出");
        });
        
        t.start();
        Thread.sleep(300);
        t.interrupt(); // 发送中断信号
        t.join();
        
        System.out.println();
        System.out.println("中断相关方法:");
        System.out.println("  - interrupt(): 设置中断标志");
        System.out.println("  - isInterrupted(): 检查中断标志(不清除)");
        System.out.println("  - interrupted(): 检查并清除中断标志(静态方法)");
        System.out.println();
        
        System.out.println("响应中断的方法:");
        System.out.println("  - Object.wait()");
        System.out.println("  - Thread.join()");
        System.out.println("  - Thread.sleep()");
        System.out.println("  - BlockingQueue.put/take");
        System.out.println("  - Lock.lockInterruptibly");
        System.out.println();
    }
}

/**
 * 优雅停止线程的示例
 */
class GracefulShutdownDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 优雅停止线程 ===\n");
        
        // 使用线程池和Future
        ExecutorService executor = Executors.newSingleThreadExecutor();
        
        Future<?> future = executor.submit(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                try {
                    System.out.println("工作中...");
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    System.out.println("收到中断信号,准备停止");
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            // 清理资源
            System.out.println("清理资源...");
        });
        
        Thread.sleep(2000);
        future.cancel(true); // 中断正在执行的任务
        executor.shutdown();
        executor.awaitTermination(5, TimeUnit.SECONDS);
        
        System.out.println("线程池已关闭");
    }
}
2.3.2 等待与通知
/**
 * 线程等待与通知
 */
public class WaitNotifyDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 线程等待与通知 ===\n");
        
        waitNotifyDemo();
        waitTimeoutDemo();
        producerConsumerDemo();
    }
    
    private static void waitNotifyDemo() throws InterruptedException {
        System.out.println("【wait/notify基础】\n");
        
        Object lock = new Object();
        
        Thread waitingThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("等待线程: 开始等待");
                    lock.wait(); // 释放锁并等待
                    System.out.println("等待线程: 被唤醒");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        
        Thread notifyThread = new Thread(() -> {
            synchronized (lock) {
                try {
                    Thread.sleep(1000);
                    System.out.println("通知线程: 发送通知");
                    lock.notify(); // 唤醒一个等待线程
                    // lock.notifyAll(); // 唤醒所有等待线程
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        
        waitingThread.start();
        Thread.sleep(100);
        notifyThread.start();
        
        waitingThread.join();
        notifyThread.join();
        
        System.out.println();
        System.out.println("使用规范:");
        System.out.println("  1. 必须在synchronized块内调用");
        System.out.println("  2. wait()会释放锁,notify()不会释放锁");
        System.out.println("  3. 建议使用while循环检查条件");
        System.out.println("  4. 优先使用notifyAll()避免信号丢失");
        System.out.println();
    }
    
    private static void waitTimeoutDemo() throws InterruptedException {
        System.out.println("【超时等待】\n");
        
        Object lock = new Object();
        
        Thread t = new Thread(() -> {
            synchronized (lock) {
                try {
                    System.out.println("开始超时等待(2秒)");
                    long start = System.currentTimeMillis();
                    lock.wait(2000); // 等待2秒
                    long elapsed = System.currentTimeMillis() - start;
                    System.out.println("等待结束,耗时: " + elapsed + "ms");
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        
        t.start();
        t.join();
        System.out.println();
    }
    
    /**
     * 生产者-消费者模式演示
     */
    private static void producerConsumerDemo() throws InterruptedException {
        System.out.println("【生产者-消费者模式】\n");
        
        class BoundedBuffer<T> {
            private final Object[] items;
            private int putIndex, takeIndex, count;
            
            public BoundedBuffer(int capacity) {
                items = new Object[capacity];
            }
            
            @SuppressWarnings("unchecked")
            public T take() throws InterruptedException {
                synchronized (this) {
                    while (count == 0) {
                        System.out.println("缓冲区为空,消费者等待");
                        wait();
                    }
                    
                    Object item = items[takeIndex];
                    items[takeIndex] = null;
                    takeIndex = (takeIndex + 1) % items.length;
                    count--;
                    
                    notifyAll();
                    return (T) item;
                }
            }
            
            public void put(T item) throws InterruptedException {
                synchronized (this) {
                    while (count == items.length) {
                        System.out.println("缓冲区已满,生产者等待");
                        wait();
                    }
                    
                    items[putIndex] = item;
                    putIndex = (putIndex + 1) % items.length;
                    count++;
                    
                    System.out.println("生产: " + item);
                    notifyAll();
                }
            }
        }
        
        BoundedBuffer<String> buffer = new BoundedBuffer<>(3);
        
        // 生产者
        Thread producer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    buffer.put("Item-" + i);
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        
        // 消费者
        Thread consumer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    String item = buffer.take();
                    System.out.println("消费: " + item);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        });
        
        producer.start();
        consumer.start();
        
        producer.join();
        consumer.join();
        
        System.out.println();
    }
}
2.3.3 join与yield
/**
 * join和yield方法
 */
public class JoinYieldDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== join和yield ===\n");
        
        joinDemo();
        yieldDemo();
    }
    
    private static void joinDemo() throws InterruptedException {
        System.out.println("【join方法】\n");
        
        System.out.println("join(): 等待目标线程结束");
        System.out.println("join(long): 超时等待");
        System.out.println();
        
        Thread t1 = new Thread(() -> {
            try {
                System.out.println("线程1开始执行");
                Thread.sleep(2000);
                System.out.println("线程1执行完毕");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        Thread t2 = new Thread(() -> {
            try {
                System.out.println("线程2开始执行");
                Thread.sleep(1000);
                System.out.println("线程2执行完毕");
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });
        
        long start = System.currentTimeMillis();
        
        t1.start();
        t2.start();
        
        System.out.println("主线程等待子线程完成...");
        t1.join(); // 等待t1完成
        t2.join(); // 等待t2完成
        
        long elapsed = System.currentTimeMillis() - start;
        System.out.println("所有子线程完成,耗时: " + elapsed + "ms");
        System.out.println();
        
        System.out.println("应用场景:");
        System.out.println("  1. 等待多个线程完成");
        System.out.println("  2. 线程间顺序控制");
        System.out.println("  3. 获取线程执行结果");
        System.out.println();
    }
    
    private static void yieldDemo() {
        System.out.println("【yield方法】\n");
        
        System.out.println("yield(): 暗示调度器让出CPU时间片");
        System.out.println();
        
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("线程1: " + i);
                Thread.yield(); // 让出CPU
            }
        });
        
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("线程2: " + i);
                Thread.yield(); // 让出CPU
            }
        });
        
        t1.start();
        t2.start();
        
        try {
            t1.join();
            t2.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        
        System.out.println();
        System.out.println("说明:");
        System.out.println("  - yield只是建议,调度器可能忽略");
        System.out.println("  - 从RUNNING变为RUNNABLE状态");
        System.out.println("  - 可能让同优先级或更高优先级的线程执行");
        System.out.println("  - 实际使用较少,可用于调试");
        System.out.println();
    }
}

2.4 守护线程

/**
 * 守护线程详解
 */
public class DaemonThreadDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 守护线程 ===\n");
        
        daemonDemo();
        daemonUseCases();
    }
    
    private static void daemonDemo() throws InterruptedException {
        System.out.println("【守护线程演示】\n");
        
        // 用户线程
        Thread userThread = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                try {
                    System.out.println("用户线程运行: " + i);
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
            System.out.println("用户线程结束");
        }, "User-Thread");
        
        // 守护线程
        Thread daemonThread = new Thread(() -> {
            int i = 0;
            while (true) {
                try {
                    System.out.println("守护线程运行: " + i++);
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    break;
                }
            }
            System.out.println("守护线程结束"); // 可能不会执行
        }, "Daemon-Thread");
        daemonThread.setDaemon(true); // 设置为守护线程
        
        System.out.println("用户线程是否为守护线程: " + userThread.isDaemon());
        System.out.println("守护线程是否为守护线程: " + daemonThread.isDaemon());
        System.out.println();
        
        userThread.start();
        daemonThread.start();
        
        // 只等待用户线程
        userThread.join();
        
        System.out.println("\n用户线程结束,JVM即将退出");
        System.out.println("守护线程也会随之结束(可能未完成)");
        System.out.println();
    }
    
    private static void daemonUseCases() {
        System.out.println("【守护线程应用场景】\n");
        
        System.out.println("典型应用:");
        System.out.println("  1. GC线程 (垃圾回收)");
        System.out.println("  2. 后台监控线程");
        System.out.println("  3. 日志写入线程");
        System.out.println("  4. 缓存清理线程");
        System.out.println();
        
        System.out.println("注意事项:");
        System.out.println("  1. setDaemon()必须在start()前调用");
        System.out.println("  2. 守护线程创建的线程默认也是守护线程");
        System.out.println("  3. 不要在守护线程中访问共享资源(可能随时终止)");
        System.out.println("  4. 守护线程中的finally块不保证执行");
        System.out.println();
        
        // 守护线程finally不保证执行示例
        System.out.println("【finally块示例】\n");
        
        Thread daemonWithFinally = new Thread(() -> {
            try {
                System.out.println("守护线程: try块");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } finally {
                // 当所有用户线程结束时,JVM退出,可能不会执行
                System.out.println("守护线程: finally块(可能不会执行)");
            }
        });
        daemonWithFinally.setDaemon(true);
        daemonWithFinally.start();
        
        // 主线程很快结束
        System.out.println("主线程即将结束");
    }
}

2.5 线程优先级

/**
 * 线程优先级
 */
public class ThreadPriorityDemo {
    
    public static void main(String[] args) {
        System.out.println("=== 线程优先级 ===\n");
        
        priorityDemo();
        priorityGuidelines();
    }
    
    private static void priorityDemo() {
        System.out.println("【优先级范围】\n");
        
        System.out.println("优先级范围: 1-10");
        System.out.println("  - MIN_PRIORITY = 1");
        System.out.println("  - NORM_PRIORITY = 5 (默认)");
        System.out.println("  - MAX_PRIORITY = 10");
        System.out.println();
        
        Thread lowPriority = new Thread(() -> {
            int count = 0;
            while (count < 10000) {
                count++;
            }
            System.out.println("低优先级线程完成: " + count);
        }, "Low-Priority");
        lowPriority.setPriority(Thread.MIN_PRIORITY);
        
        Thread highPriority = new Thread(() -> {
            int count = 0;
            while (count < 10000) {
                count++;
            }
            System.out.println("高优先级线程完成: " + count);
        }, "High-Priority");
        highPriority.setPriority(Thread.MAX_PRIORITY);
        
        highPriority.start();
        lowPriority.start();
        
        System.out.println();
        System.out.println("说明:");
        System.out.println("  - 优先级只是建议,实际调度取决于操作系统");
        System.out.println("  - 不同操作系统实现不同");
        System.out.println("  - 高优先级线程获得CPU时间的概率更高");
        System.out.println("  - 但不保证执行顺序");
        System.out.println();
    }
    
    private static void priorityGuidelines() {
        System.out.println("【优先级使用建议】\n");
        
        System.out.println("❌ 不推荐:");
        System.out.println("  - 依赖优先级控制程序逻辑");
        System.out.println("  - 频繁修改优先级");
        System.out.println("  - 假设优先级能保证执行顺序");
        System.out.println();
        
        System.out.println("✅ 推荐做法:");
        System.out.println("  - 使用默认优先级");
        System.out.println("  - 通过任务队列控制执行顺序");
        System.out.println("  - 使用线程池管理线程");
        System.out.println("  - 让操作系统调度器决定");
        System.out.println();
    }
}

三、可运行Java代码示例

完整示例:多线程协作

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 多线程协作完整示例
 */
public class ThreadCoordinationDemo {
    
    public static void main(String[] args) throws InterruptedException {
        System.out.println("=== 多线程协作示例 ===\n");
        
        // 示例1: 并行计算
        parallelComputation();
        
        // 示例2: 阶段性任务
        phasedTask();
        
        // 示例3: 线程间通信
        threadCommunication();
    }
    
    /**
     * 并行计算示例
     */
    private static void parallelComputation() throws InterruptedException {
        System.out.println("【并行计算】\n");
        
        int[] array = new int[1000000];
        for (int i = 0; i < array.length; i++) {
            array[i] = i + 1;
        }
        
        int threadCount = 4;
        AtomicInteger totalSum = new AtomicInteger(0);
        CountDownLatch latch = new CountDownLatch(threadCount);
        
        int chunkSize = array.length / threadCount;
        
        long start = System.currentTimeMillis();
        
        for (int i = 0; i < threadCount; i++) {
            final int startIdx = i * chunkSize;
            final int endIdx = (i == threadCount - 1) ? array.length : startIdx + chunkSize;
            
            new Thread(() -> {
                int sum = 0;
                for (int j = startIdx; j < endIdx; j++) {
                    sum += array[j];
                }
                totalSum.addAndGet(sum);
                latch.countDown();
            }, "Calculator-" + i).start();
        }
        
        latch.await();
        
        long elapsed = System.currentTimeMillis() - start;
        
        System.out.println("并行计算结果: " + totalSum.get());
        System.out.println("耗时: " + elapsed + "ms");
        
        // 单线程对比
        start = System.currentTimeMillis();
        long singleThreadSum = 0;
        for (int value : array) {
            singleThreadSum += value;
        }
        elapsed = System.currentTimeMillis() - start;
        System.out.println("单线程结果: " + singleThreadSum);
        System.out.println("单线程耗时: " + elapsed + "ms");
        System.out.println();
    }
    
    /**
     * 阶段性任务示例
     */
    private static void phasedTask() throws InterruptedException {
        System.out.println("【阶段性任务】\n");
        
        CyclicBarrier barrier = new CyclicBarrier(3, () -> {
            System.out.println("=== 阶段完成 ===\n");
        });
        
        for (int i = 0; i < 3; i++) {
            final int taskId = i;
            new Thread(() -> {
                try {
                    // 阶段1
                    System.out.println("任务" + taskId + ": 阶段1执行");
                    Thread.sleep((long) (Math.random() * 1000));
                    barrier.await();
                    
                    // 阶段2
                    System.out.println("任务" + taskId + ": 阶段2执行");
                    Thread.sleep((long) (Math.random() * 1000));
                    barrier.await();
                    
                    // 阶段3
                    System.out.println("任务" + taskId + ": 阶段3执行");
                } catch (Exception e) {
                    Thread.currentThread().interrupt();
                }
            }, "Task-" + i).start();
        }
        
        Thread.sleep(3000);
        System.out.println();
    }
    
    /**
     * 线程间通信示例
     */
    private static void threadCommunication() throws InterruptedException {
        System.out.println("【线程间通信】\n");
        
        BlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
        AtomicInteger producedCount = new AtomicInteger(0);
        AtomicInteger consumedCount = new AtomicInteger(0);
        
        // 生产者
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    String item = "Item-" + i;
                    queue.put(item);
                    producedCount.incrementAndGet();
                    System.out.println("生产: " + item + " (队列大小: " + queue.size() + ")");
                    Thread.sleep(100);
                }
                queue.put("END"); // 结束信号
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "Producer");
        
        // 消费者
        Thread consumer = new Thread(() -> {
            try {
                while (true) {
                    String item = queue.take();
                    if ("END".equals(item)) {
                        break;
                    }
                    consumedCount.incrementAndGet();
                    System.out.println("消费: " + item + " (队列大小: " + queue.size() + ")");
                    Thread.sleep(150);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, "Consumer");
        
        producer.start();
        consumer.start();
        
        producer.join();
        consumer.join();
        
        System.out.println("\n生产总数: " + producedCount.get());
        System.out.println("消费总数: " + consumedCount.get());
        System.out.println();
    }
}

四、总结与最佳实践

核心要点回顾

分类内容
创建方式继承Thread、实现Runnable、实现Callable
线程状态NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
基本操作start、interrupt、join、yield、sleep、wait/notify
守护线程后台服务线程,随用户线程结束而终止

最佳实践

/**
 * 线程最佳实践
 */
public class ThreadBestPractices {
    
    public static void main(String[] args) {
        System.out.println("=== 线程最佳实践 ===\n");
        
        System.out.println("1. 命名规范");
        System.out.println("   - 使用有意义的线程名称");
        System.out.println("   - 便于调试和监控");
        System.out.println("   Thread t = new Thread(task, 'worker-thread-1');");
        System.out.println();
        
        System.out.println("2. 正确停止线程");
        System.out.println("   - 使用interrupt()而不是stop()");
        System.out.println("   - 检查中断标志");
        System.out.println("   - 正确处理InterruptedException");
        System.out.println();
        
        System.out.println("3. 使用线程池");
        System.out.println("   - 避免频繁创建销毁线程");
        System.out.println("   - 控制并发数量");
        System.out.println("   - ExecutorService executor = Executors.newFixedThreadPool(10);");
        System.out.println();
        
        System.out.println("4. 异常处理");
        System.out.println("   - 设置UncaughtExceptionHandler");
        System.out.println("   - 记录异常日志");
        System.out.println();
        
        System.out.println("5. 资源管理");
        System.out.println("   - 使用try-with-resources");
        System.out.println("   - finally块中释放资源");
        System.out.println();
        
        System.out.println("6. 避免死锁");
        System.out.println("   - 固定加锁顺序");
        System.out.println("   - 使用超时锁");
        System.out.println("   - 减小锁粒度");
        System.out.println();
        
        // 演示UncaughtExceptionHandler
        Thread t = new Thread(() -> {
            throw new RuntimeException("测试异常");
        });
        t.setName("Exception-Thread");
        t.setUncaughtExceptionHandler((thread, throwable) -> {
            System.err.println("线程 " + thread.getName() + " 发生异常: " + throwable.getMessage());
        });
        t.start();
        
        try {
            t.join();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}

常见陷阱

/**
 * 线程常见陷阱
 */
public class ThreadPitfalls {
    
    public static void main(String[] args) {
        System.out.println("=== 线程常见陷阱 ===\n");
        
        System.out.println("1. 直接调用run()而不是start()");
        System.out.println("   ❌ thread.run();  // 不会创建新线程");
        System.out.println("   ✅ thread.start(); // 创建新线程");
        System.out.println();
        
        System.out.println("2. 重复调用start()");
        System.out.println("   ❌ thread.start(); thread.start(); // 抛异常");
        System.out.println();
        
        System.out.println("3. 在构造函数中启动线程");
        System.out.println("   ❌ this引用可能泄露");
        System.out.println("   ✅ 使用工厂方法或Builder");
        System.out.println();
        
        System.out.println("4. 忽略InterruptedException");
        System.out.println("   ❌ catch (InterruptedException e) {} // 吞掉异常");
        System.out.println("   ✅ catch (InterruptedException e) { Thread.currentThread().interrupt(); }");
        System.out.println();
        
        System.out.println("5. wait()不在循环中");
        System.out.println("   ❌ if (condition) { wait(); }");
        System.out.println("   ✅ while (condition) { wait(); }");
        System.out.println();
        
        System.out.println("6. 在守护线程中操作共享资源");
        System.out.println("   守护线程随时可能终止,数据可能不完整");
        System.out.println();
        
        System.out.println("7. 过度同步");
        System.out.println("   - 导致性能问题");
        System.out.println("   - 可能死锁");
        System.out.println("   - 保持同步块短小");
        System.out.println();
    }
}

相关工具类

工具类用途
CountDownLatch一次性门闩,等待多线程完成
CyclicBarrier循环栅栏,多线程同步点
Semaphore信号量,控制并发数
Exchanger线程间数据交换
Phaser阶段同步器

扩展阅读

  • 《Java并发编程实战》:并发编程经典
  • 《Java并发编程的艺术》:深入原理
  • JDK文档:Thread类、java.util.concurrent包