Java线程详解

📌摘要

本文系统讲解了Java中线程的基础知识、线程同步机制、并发工具类、高级主题(如 Fork/Join 和 CompletableFuture)、性能优化策略以及实际项目中的应用案例。每节均配有完整的示例代码,适合初学者入门和中级开发者深入学习。


🎯一、引言

在现代多核处理器架构下,并发编程已成为高性能应用开发的核心技能之一。Java自诞生之初就内置了对线程的支持,使得开发者能够轻松地实现多线程程序。本文将系统讲解Java线程的基础知识、同步机制、并发工具类、高级主题以及最佳实践,帮助你构建稳定、高效的并发程序。


🧱二、Java线程基础

1. 什么是线程?

线程是操作系统调度的最小单位,属于进程的一部分。多个线程共享同一个进程的资源(如内存、文件句柄等),相比进程切换开销更小。

进程 vs 线程

  • 进程:独立地址空间,资源隔离。
  • 线程:轻量级执行单元,共享进程资源。

2. 创建线程的方法

方法一:继承 Thread

class MyThread extends Thread {
    public void run() {
        System.out.println("Hello from thread: " + Thread.currentThread().getName());
    }
}

public class Main {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start(); // 启动线程
    }
}

方法二:实现 Runnable 接口(推荐)

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("Running in thread: " + Thread.currentThread().getName());
    }
}

public class Main {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable(), "MyWorker");
        t.start();
    }
}

方法三:使用 ExecutorService(推荐用于生产环境)

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Main {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(() -> System.out.println("Task executed by thread pool"));
        executor.shutdown();
    }
}

3. 线程生命周期

Java 中线程有六种状态:

状态 描述
NEW 刚创建未启动
RUNNABLE 正在运行或等待CPU时间片
BLOCKED 等待进入同步方法/代码块
WAITING 无限期等待其他线程唤醒
TIMED_WAITING 定时等待
TERMINATED 线程执行完毕

4. 线程优先级

Java中线程优先级范围是1~10,默认值为5。

Thread t1 = new Thread(() -> System.out.println("T1"));
Thread t2 = new Thread(() -> System.out.println("T2"));

t1.setPriority(Thread.MIN_PRIORITY); // 1
t2.setPriority(Thread.MAX_PRIORITY); // 10

t1.start();
t2.start();

⚠️ 注意:线程优先级只是提示,并不保证高优先级一定先执行。


🔐三、线程同步与通信

1. 线程安全问题

当多个线程同时访问共享资源时,可能会出现数据不一致的问题。

class Counter {
    int count = 0;

    void increment() {
        count++;
    }
}

多线程调用 increment() 可能导致结果错误。

2. 同步机制

使用 synchronized 关键字

class Counter {
    private int count = 0;

    synchronized void increment() {
        count++;
    }

    int getCount() {
        return count;
    }
}

显式锁 ReentrantLock

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Counter {
    private final Lock lock = new ReentrantLock();
    private int count = 0;

    void increment() {
        lock.lock();
        try {
            count++;
        } finally {
            lock.unlock();
        }
    }
}

3. 线程间通信

使用 wait() / notify() 实现线程协作。

class SharedResource {
    boolean isAvailable = false;

    synchronized void produce() throws InterruptedException {
        while (isAvailable) wait();
        isAvailable = true;
        System.out.println("Produced");
        notify();
    }

    synchronized void consume() throws InterruptedException {
        while (!isAvailable) wait();
        isAvailable = false;
        System.out.println("Consumed");
        notify();
    }
}

🧰四、并发工具类

1. CountDownLatch

适用于主线程等待多个子线程完成任务后继续执行。

import java.util.concurrent.CountDownLatch;

public class LatchExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(3);

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " working...");
                latch.countDown();
            }).start();
        }

        latch.await(); // 阻塞直到计数归零
        System.out.println("All threads completed.");
    }
}

2. CyclicBarrier

多个线程互相等待,到达屏障点后再一起继续执行。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class BarrierExample {
    public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All arrived!"));

        for (int i = 0; i < 3; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " arrived.");
                try {
                    barrier.await();
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

3. Semaphore

控制同时访问的线程数量。

import java.util.concurrent.Semaphore;

public class SemaphoreExample {
    public static void main(String[] args) {
        Semaphore semaphore = new Semaphore(2); // 允许两个线程并发

        for (int i = 0; i < 5; i++) {
            new Thread(() -> {
                try {
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + " is using resource.");
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    semaphore.release();
                }
            }).start();
        }
    }
}

4. Exchanger

用于两个线程之间交换数据。

import java.util.concurrent.Exchanger;

public class ExchangerExample {
    public static void main(String[] args) {
        Exchanger<String> exchanger = new Exchanger<>();

        new Thread(() -> {
            String data = "Data from Thread 1";
            try {
                String result = exchanger.exchange(data);
                System.out.println("Received: " + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "T1").start();

        new Thread(() -> {
            String data = "Data from Thread 2";
            try {
                String result = exchanger.exchange(data);
                System.out.println("Received: " + result);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, "T2").start();
    }
}

🚀五、高级主题

1. Fork/Join 框架

适用于分治型任务,如排序、搜索等。

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

class SumTask extends RecursiveTask<Integer> {
    private final int[] array;
    private final int start, end;

    SumTask(int[] array, int start, int end) {
        this.array = array;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Integer compute() {
        if (end - start <= 2) {
            int sum = 0;
            for (int i = start; i < end; i++) {
                sum += array[i];
            }
            return sum;
        }

        int mid = (start + end) / 2;
        SumTask left = new SumTask(array, start, mid);
        SumTask right = new SumTask(array, mid, end);

        left.fork();
        right.fork();

        return left.join() + right.join();
    }
}

public class ForkJoinExample {
    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8};
        ForkJoinPool pool = new ForkJoinPool();
        int result = pool.invoke(new SumTask(array, 0, array.length));
        System.out.println("Total sum: " + result);
    }
}

2. CompletableFuture

Java 8 引入的异步编程新方式。

import java.util.concurrent.CompletableFuture;

public class FutureExample {
    public static void main(String[] args) {
        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("Task running in async thread: " + Thread.currentThread().getName());
        });

        future.join(); // 等待任务完成
    }
}

3. 虚拟线程(Java 19+)

轻量级线程,极大提升并发能力。

// JDK 21 示例
public class VirtualThreadExample {
    public static void main(String[] args) throws Exception {
        Thread.ofVirtual().start(() -> {
            System.out.println("Running in virtual thread: " + Thread.currentThread());
        });
    }
}

⚙️六、性能优化与最佳实践

1. 线程池的选择与配置

ExecutorService fixedPool = Executors.newFixedThreadPool(4); // CPU密集型
ExecutorService cachedPool = Executors.newCachedThreadPool(); // IO密集型
ExecutorService singlePool = Executors.newSingleThreadExecutor(); // 单线程顺序执行

2. 减少上下文切换开销

  • 控制线程数量,避免过多线程竞争资源。
  • 使用批处理减少频繁创建线程。

3. 错误处理与日志记录

Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
    System.err.println("Uncaught exception in thread " + t.getName() + ": " + e.getMessage());
});

🧪七、案例研究

1. 实际项目中的线程应用

以电商系统为例,订单创建后需要异步更新库存、发送短信、写入日志等操作,可使用线程池进行解耦:

ExecutorService orderExecutor = Executors.newFixedThreadPool(4);

orderExecutor.submit(() -> updateInventory(order));
orderExecutor.submit(() -> sendNotification(user));
orderExecutor.submit(() -> logOrder(order));

2. 性能测试与分析

使用 JMH 进行基准测试,比较同步与异步处理性能差异。

@Benchmark
public void testSyncProcessing() {
    processOrdersSynchronously();
}

@Benchmark
public void testAsyncProcessing() {
    processOrdersAsynchronously();
}

🧠八、总结

Java线程是构建高性能、响应式系统的关键技术。通过掌握线程的生命周期、同步机制、并发工具类和高级特性,你可以写出更加高效、稳定的并发程序。随着虚拟线程、结构化并发等新技术的引入,Java在并发编程领域的优势将进一步增强。



  • 如果你在学习过程中遇到任何疑问,欢迎在评论区留言交流!

  • 👍 如果你觉得这篇文章对你有帮助,别忘了点赞、收藏、转发哦!

posted @ 2025-06-20 23:13  bug糕手  阅读(62)  评论(0)    收藏  举报