Java 中的线程是并发编程的核心。下面从基础概念到实际使用系统地讲一讲。一、进程 vs 线程进程操作系统分配资源的基本单位每个进程有独立的内存空间。线程CPU 调度的基本单位同一进程内的多个线程共享进程的内存空间堆、方法区但各自有独立的栈和程序计数器。线程更轻量创建和切换开销比进程小但共享内存也带来了线程安全问题。二、创建线程的方式1. 继承 Thread 类classMyThreadextendsThread{Overridepublicvoidrun(){System.out.println(线程运行中Thread.currentThread().getName());}}newMyThread().start();// 注意是 start() 不是 run()start()会启动新线程并让 JVM 调用run()直接调用run()只是普通方法调用不会开新线程。2. 实现 Runnable 接口推荐Runnabletask()-System.out.println(任务执行);newThread(task).start();优点避免单继承限制任务与线程解耦。3. 实现 Callable FutureTaskCallableIntegercallable()-11;FutureTaskIntegerfutureTasknewFutureTask(callable);newThread(futureTask).start();IntegerresultfutureTask.get();// 阻塞获取返回值相比 Runnable可以有返回值、可以抛异常。4. 线程池实际开发最常用ExecutorServicepoolExecutors.newFixedThreadPool(4);pool.submit(()-System.out.println(池中线程执行));pool.shutdown();生产环境推荐用ThreadPoolExecutor手动创建避免Executors的坑如无界队列导致 OOM。三、线程的生命周期Java 线程状态定义在Thread.State枚举中共 6 种状态说明NEW创建了但未调用 start()RUNNABLE可运行包括正在运行和就绪等待 CPUBLOCKED等待获取 synchronized 锁WAITING无限期等待wait()、join()、park()TIMED_WAITING限时等待sleep、wait(ms)、join(ms)TERMINATED已结束转换示意NEW → start() → RUNNABLE ⇄ BLOCKED/WAITING/TIMED_WAITING → TERMINATED四、常用方法方法作用start()启动线程run()线程执行体sleep(ms)让当前线程休眠不释放锁join()等待该线程结束yield()让出 CPU回到就绪状态interrupt()中断线程设置中断标志isInterrupted()检查中断标志setDaemon(true)设为守护线程JVM 退出时不管它⚠️已废弃stop()、suspend()、resume()容易造成死锁或数据不一致。五、线程安全问题多个线程访问共享可变数据时可能出错。经典例子classCounter{privateintcount0;publicvoidincrement(){count;}// 非原子操作}count实际是「读-改-写」三步多线程下会丢失更新。解决方案1. synchronized内置锁publicsynchronizedvoidincrement(){count;}// 或synchronized(lock){count;}2. Lock显式锁LocklocknewReentrantLock();lock.lock();try{count;}finally{lock.unlock();}比 synchronized 更灵活可中断、可超时、公平锁。3. 原子类CASAtomicIntegercountnewAtomicInteger(0);count.incrementAndGet();基于 CAS无锁性能好。4. volatile保证可见性和有序性但不保证原子性。适合状态标志位。六、线程间通信wait / notify / notifyAll必须在 synchronized 块中调用且锁对象一致。synchronized(lock){while(!condition)lock.wait();// 释放锁并等待// 处理lock.notifyAll();// 唤醒其他线程}⚠️ 用while而非if防止虚假唤醒。其他工具CountDownLatch等待 N 个任务完成CyclicBarrier一组线程互相等待Semaphore控制并发数量BlockingQueue生产者-消费者模型七、JMMJava 内存模型理解线程必须了解 JMM每个线程有自己的工作内存共享变量存在主内存线程读写变量要经过工作内存导致可见性问题happens-before规则保证某些操作的可见性如锁的释放先于获取、volatile 写先于读。八、最佳实践优先用线程池不要频繁 new Thread。给线程起名字方便排查问题。缩小锁范围避免锁嵌套。优先用并发容器ConcurrentHashMap、CopyOnWriteArrayList代替同步包装。避免死锁按固定顺序获取锁、使用超时锁。捕获异常线程内未捕获异常会导致线程静默死亡可设置UncaughtExceptionHandler。