冬月小站

第七章、多线程编程

Feb 20, 2025
28
0

Java多线程编程是实现并发程序的重要技术,能够有效提升程序性能和资源利用率。以下是Java多线程的核心知识点及实践指南:


一、线程创建与管理

  1. 创建线程的三种方式

    • 继承Thread类

      java

      class MyThread extends Thread {
          public void run() {
              System.out.println("Thread running");
          }
      }
      new MyThread().start();
    • 实现Runnable接口(推荐,避免单继承局限):

      java

      class MyTask implements Runnable {
          public void run() {
              System.out.println("Task running");
          }
      }
      new Thread(new MyTask()).start();
    • 实现Callable接口(支持返回值):

      java

      class MyCallable implements Callable<String> {
          public String call() throws Exception {
              return "Callable result";
          }
      }
      FutureTask<String> futureTask = new FutureTask<>(new MyCallable());
      new Thread(futureTask).start();
      System.out.println(futureTask.get()); // 获取返回值
  2. 线程池(ThreadPoolExecutor)

    • 手动创建线程池(推荐方式):

      java

      int corePoolSize = 5;
      int maxPoolSize = 10;
      long keepAliveTime = 1L;
      BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(100);
      ThreadPoolExecutor executor = new ThreadPoolExecutor(
          corePoolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, workQueue
      );
      executor.execute(() -> System.out.println("Task executed"));
    • 常用线程池类型

      • FixedThreadPool:固定线程数,适合负载较重的服务器。

      • CachedThreadPool:线程数按需创建,适合短期异步任务。

      • SingleThreadExecutor:单个线程顺序执行任务。


二、线程同步与锁机制

  1. synchronized关键字

    • 同步方法

      java

      public synchronized void syncMethod() {
          // 同步代码
      }
    • 同步代码块

      java

      public void method() {
          synchronized(this) {
              // 同步代码
          }
      }
  2. ReentrantLock(可重入锁)

    java

    private final Lock lock = new ReentrantLock();
    public void performTask() {
        lock.lock();
        try {
            // 临界区代码
        } finally {
            lock.unlock();
        }
    }
  3. ReadWriteLock(读写锁)

    java

    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    public void readData() {
        rwLock.readLock().lock();
        try {
            // 读操作
        } finally {
            rwLock.readLock().unlock();
        }
    }
    public void writeData() {
        rwLock.writeLock().lock();
        try {
            // 写操作
        } finally {
            rwLock.writeLock().unlock();
        }
    }
  4. 原子类(Atomic Classes)

    java

    private AtomicInteger count = new AtomicInteger(0);
    public void increment() {
        count.incrementAndGet(); // 原子操作
    }

三、线程间通信

  1. wait()/notify()机制

    java

    synchronized(lock) {
        while (conditionNotMet) {
            lock.wait(); // 释放锁并等待
        }
        // 执行任务
        lock.notifyAll(); // 唤醒所有等待线程
    }
  2. Condition接口(配合Lock使用)

    java

    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    public void awaitMethod() throws InterruptedException {
        lock.lock();
        try {
            condition.await(); // 类似wait()
        } finally {
            lock.unlock();
        }
    }
    public void signalMethod() {
        lock.lock();
        try {
            condition.signal(); // 类似notify()
        } finally {
            lock.unlock();
        }
    }

四、并发工具类

  1. CountDownLatch(倒计时门闩)

    java

    CountDownLatch latch = new CountDownLatch(3);
    // 线程完成任务后调用latch.countDown()
    latch.await(); // 主线程等待所有任务完成
  2. CyclicBarrier(循环屏障)

    java

    CyclicBarrier barrier = new CyclicBarrier(3, () -> 
        System.out.println("All threads reached barrier"));
    // 线程调用barrier.await()等待其他线程
  3. Semaphore(信号量)

    java

    Semaphore semaphore = new Semaphore(5); // 允许5个线程同时访问
    semaphore.acquire(); // 获取许可
    try {
        // 访问资源
    } finally {
        semaphore.release(); // 释放许可
    }
  4. Exchanger(交换器)

    java

    Exchanger<String> exchanger = new Exchanger<>();
    // 线程A
    String dataA = exchanger.exchange("Data from A");
    // 线程B
    String dataB = exchanger.exchange("Data from B");

五、高级并发特性

  1. CompletableFuture(异步编程)

    java

    CompletableFuture.supplyAsync(() -> "Hello")
        .thenApplyAsync(s -> s + " World")
        .thenAccept(System.out::println);
  2. Fork/Join框架(分治任务)

    java

    class MyTask extends RecursiveTask<Integer> {
        protected Integer compute() {
            // 分解任务并合并结果
        }
    }
    ForkJoinPool pool = new ForkJoinPool();
    pool.invoke(new MyTask());
  3. ThreadLocal(线程局部变量)

    java

    private static ThreadLocal<SimpleDateFormat> dateFormat = 
        ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd"));

六、避免常见问题

  • 死锁预防:按固定顺序获取锁,使用尝试锁(tryLock())。

  • 资源竞争:最小化同步代码块,使用并发集合(如ConcurrentHashMap)。

  • 内存可见性:使用volatile变量或原子类确保修改可见性。

  • 线程泄漏:确保线程池正确关闭,任务处理异常。


七、性能调优建议

  • 合理设置线程池大小

    • CPU密集型:线程数 = CPU核心数 + 1

    • IO密集型:线程数 = CPU核心数 * (1 + 平均等待时间/计算时间)

  • 减少锁竞争:使用分段锁、无锁数据结构(如Disruptor框架)。

  • 监控工具:使用JConsole、VisualVM分析线程状态,检测死锁。


示例:生产者-消费者模型

java

BlockingQueue<Integer> queue = new LinkedBlockingQueue<>(10);

// 生产者
new Thread(() -> {
    while (true) {
        int num = produceItem();
        queue.put(num); // 阻塞直到队列有空位
    }
}).start();

// 消费者
new Thread(() -> {
    while (true) {
        int num = queue.take(); // 阻塞直到队列有元素
        consumeItem(num);
    }
}).start();

掌握这些核心概念和工具,能够有效开发高效、健壮的Java多线程应用。实际开发中需结合具体场景选择合适的并发策略,并通过测试确保线程安全与性能达标。