java多线程

 


⚙️ 一、线程基础概念

  1. ​线程与进程​

    • ​进程​​:操作系统资源分配的基本单位(如独立内存空间),例如一个运行的Java程序。
    • ​线程​​:CPU调度的最小单位,共享进程资源(堆内存),多线程可并发执行任务。
    • ​核心价值​​:提升吞吐量(并行处理)、增强响应性(避免阻塞)、高效利用资源(如I/O等待时执行其他任务)。
  2. ​线程生命周期​

    • ​新建(NEW)​​:通过new Thread()创建但未启动。
    • ​可运行(RUNNABLE)​​:调用start()后进入就绪状态,等待CPU调度。
    • ​阻塞/等待​​:包括BLOCKED(锁竞争)、WAITING(无限期等待)、TIMED_WAITING(超时等待)。
    • ​终止(TERMINATED)​​:run()执行完毕或异常退出。

🛠️ 二、线程创建方式

​方式​​示例代码​​适用场景​​优缺点​
​继承Thread类​ class MyThread extends Thread { run() {...} }
new MyThread().start();
简单逻辑 ❌ 单继承限制,资源共享需静态变量
​实现Runnable接口​ class MyTask implements Runnable { run() {...} }
new Thread(task).start();
需资源共享、避免单继承限制 ✅ 推荐,逻辑与线程控制分离
​实现Callable接口​ Callable<String> task = () -> "结果";
Future<String> future = executor.submit(task);
需返回值、异步任务 ✅ 支持Future获取结果,可配合线程池

💡 ​​关键区别​​:

  • Runnable无返回值,Callable有返回值(通过Future.get()获取)。
  • start()启动新线程,run()直接调用则变为普通方法(仍在当前线程)。

🔒 三、线程安全与同步

  1. ​问题根源​

    • ​竞态条件​​:多线程同时修改共享数据(如count++非原子操作)。
    • ​可见性问题​​:线程缓存导致数据修改未及时同步到主存。
    • ​有序性问题​​:指令重排打乱执行顺序。
  2. ​同步解决方案​

    • synchronized关键字​
      • 修饰实例方法:锁对象为this
      • 修饰静态方法:锁对象为类Class。
      • 同步代码块:synchronized(lockObj) { ... }
    • ReentrantLock
      • 更灵活:支持公平锁、可中断锁、尝试获取锁(tryLock())。
      private final ReentrantLock lock = new ReentrantLock();
      lock.lock();
      try { /* 临界区 */ } 
      finally { lock.unlock(); }
    • ​原子类​​:AtomicIntegerAtomicReference等,基于CAS实现无锁安全操作。
    • volatile​:仅保证可见性和禁止指令重排,不保证原子性(适用一写多读场景)。

⚡️ 四、线程池(核心实践)

  1. ​为何使用线程池?​

    • 避免频繁创建/销毁线程的开销(类比“招聘/解雇员工成本高”)。
    • 控制并发线程数,防止资源耗尽。
  2. ​常用线程池(通过Executors创建)​

    ​类型​​特点​
    newFixedThreadPool(n) 固定大小,任务队列无界
    newCachedThreadPool() 线程数弹性伸缩,空闲线程60秒回收
    newSingleThreadExecutor() 单线程串行执行
    newScheduledThreadPool(n) 支持定时/周期性任务
  3. ​基础用法​

    ExecutorService pool = Executors.newFixedThreadPool(4);
    pool.execute(() -> System.out.println("任务执行"));
    pool.shutdown(); // 优雅关闭(等待已提交任务完成)

🚀 五、高级特性与工具类

  1. ​线程通信​

    • wait()/notify()​:需在synchronized块内调用,wait()释放锁并等待,notify()唤醒一个等待线程(notifyAll()唤醒所有)。
    • ​典型场景​​:生产者-消费者模型(需配合条件判断避免虚假唤醒)。
  2. ​并发工具类​

    • CountDownLatch​:倒计时门闩(等待多个任务完成)。
    • CyclicBarrier​:循环栅栏(线程到达屏障后统一执行后续逻辑)。
    • Semaphore​:信号量(控制并发访问资源数)。
  3. ​Fork/Join框架​

    • 分治思想:将大任务拆分为子任务并行执行,再合并结果(如归并排序)。

⚠️ 六、常见问题与规避

  1. ​死锁​

    • ​条件​​:互斥、持有并等待、不可抢占、循环等待。
    • ​规避​​:按固定顺序获取锁、设置锁超时(tryLock(timeout))、避免嵌套锁。
  2. ​性能优化​

    • 缩小同步范围(减少锁竞争)。
    • 优先使用线程安全集合(如ConcurrentHashMap)。
    • 避免过度创建线程(通过线程池控制)。

💎 总结建议

  • ​优先选择​​:Runnable + ​​线程池​​,资源利用高效且易管理。
  • ​同步机制​​:简单场景用synchronized,复杂需求(如超时控制)选ReentrantLock
  • ​避坑指南​​:
    • 禁止直接调用run()代替start()
    • 静态方法同步锁是类对象,非静态方法锁是实例对象;
    • 高并发场景通过ThreadLocal为线程提供独立变量副本(如数据库连接)。
posted @ 2025-06-19 09:51  joshua317  阅读(7)  评论(0)    收藏  举报