Java开发工程师必须掌握的线程知识指南

一、线程基础概念

1.1 线程生命周期

  1. 新建状态(New):new Thread 此时线程对象已经被创建,但还没有开始运行。

  2. 就绪状态(Runnable):调用start()方法后,线程进入就绪状态。此时线程已经准备好运行,但可能还没有被分配到CPU时间片。

  3. 运行状态(Running):当线程获得CPU时间片并开始执行时,线程进入运行状态,执行run()方法

  4. 阻塞状态(Blocked):当线程因为某些原因无法继续执行时,线程进入阻塞状态。阻塞状态可以分为多种类型,如等待I/O、等待锁、等待信号等。

  5. 等待状态(Waiting):当线程需要等待某些条件满足时,线程进入等待状态。等待状态可以通过wait()方法、join()方法等实现。

  6. 计时等待状态(Timed Waiting):当线程需要等待一定时间或者等待某些条件满足时,线程进入计时等待状态。计时等待状态可以通过sleep()方法、wait(timeout)方法等实现。

  7. 终止状态(Terminated):当线程完成了任务或者因为异常等原因退出时,线程进入终止状态。此时线程的生命周期结束。

生命周期详细推荐阅读:https://www.cnblogs.com/huigui-mint/p/17468736.html

1.2 创建线程方式

  • 继承Thread类(不推荐)
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("这是通过继承Thread类创建的线程在执行任务");
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}
  • 实现Runnable接口
class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("这是通过实现Runnable接口创建的线程在执行任务");
    }
}

public class Main {
    public static void main(String[] args) {
        MyRunnable myRunnable = new MyRunnable();
        Thread thread = new Thread(myRunnable);
        thread.start();
    }
}
  • 实现Callable接口 + FutureTask
class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "这是通过实现Callable接口创建的线程执行结果";
    }
}

public class Main {
    public static void main(String[] args) {
        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask<>(myCallable);
        Thread thread = new Thread(futureTask);
        thread.start();
        try {
            String result = futureTask.get();
            System.out.println(result);
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }
    }
}
  • 线程池创建(推荐方式,一般使用构造函数)
class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "正在执行任务");
    }
}

public class Main {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 5; i++) {
            executorService.submit(new MyTask());
        }
        executorService.shutdown();
    }
}

二、线程同步机制

2.1 synchronized关键字

// 实例方法锁
public synchronized void method() {}

// 代码块锁
public void method() {
    synchronized(this) {
        // 临界区
    }
}

// 类锁
public static synchronized void staticMethod() {}

2.2 Lock体系

ReentrantLock lock = new ReentrantLock(true); // 公平锁
lock.lock();
try {
    // 临界区
} finally {
    lock.unlock();
}

2.3 volatile关键字

  • 保证可见性
  • 禁止指令重排序
  • 不保证原子性(需配合synchronized或原子类)

三、线程间协作

3.1 wait/notify机制

synchronized(lock) {
    while(condition) {
        lock.wait(); // 释放锁等待
    }
    // 处理逻辑
    lock.notifyAll();
}

3.2 Condition接口

Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();

lock.lock();
try {
    condition.await();
    condition.signal();
} finally {
    lock.unlock();
}

四、并发工具类

4.1 CountDownLatch

CountDownLatch latch = new CountDownLatch(3);
// 多个线程调用 latch.countDown()
latch.await(); // 主线程等待

4.2 CyclicBarrier

CyclicBarrier barrier = new CyclicBarrier(3, () -> {
    System.out.println("所有线程到达屏障");
});

4.3 Semaphore

Semaphore semaphore = new Semaphore(5);
semaphore.acquire(); // 获取许可
semaphore.release(); // 释放许可

五、线程安全解决方案

5.1 不可变对象

public final class ImmutableObject {
    private final int value;
    // 构造器初始化
}

5.2 并发容器

  • ConcurrentHashMap(分段锁/CAS)
  • CopyOnWriteArrayList(写时复制)
  • ConcurrentLinkedQueue(无锁队列)

六、线程池核心知识

6.1 七大参数

new ThreadPoolExecutor(
    corePoolSize,  // 核心线程数
    maximumPoolSize, // 最大线程数
    keepAliveTime,  // 空闲线程存活时间
    TimeUnit,       // 时间单位
    workQueue,      // 任务队列
    threadFactory,  // 线程工厂
    handler         // 拒绝策略
);

6.2 四种拒绝策略

  • AbortPolicy(默认抛出异常)
  • CallerRunsPolicy(调用者执行)
  • DiscardPolicy(静默丢弃)
  • DiscardOldestPolicy(丢弃最老任务)

七、常见问题及解决方案

7.1 死锁预防

  • 避免嵌套锁
  • 使用定时锁(tryLock)
  • 按固定顺序获取锁

7.2 上下文切换优化

  • 减少同步代码块大小
  • 使用无锁数据结构
  • 合理设置线程池大小

八、最佳实践

  1. 优先使用线程池管理线程
  2. 同步代码块尽量缩小范围
  3. 使用并发容器替代同步容器
  4. 关注ThreadLocal内存泄漏问题
  5. 使用jstack分析线程状态
  6. 推荐使用Java8的CompletableFuture

总结

掌握Java多线程开发需要理解线程基础、同步机制、线程协作等核心概念,同时要熟悉JUC工具包的使用。建议通过实际项目中的并发场景(如秒杀系统、批量处理等)加深理解,并使用VisualVM、Arthas等工具进行线程状态分析。良好的并发程序设计需要平衡性能与线程安全,避免过度同步导致的性能问题。

你可能感兴趣的:(java,jvm,开发语言)