JDK8 中线程实现方法与底层逻辑详解

相关文章

Java 线程演进史:从 JDK8 到 JDK21 的并发编程革命(一)https://blog.csdn.net/weixin_37549398/article/details/156024433?spm=1011.2415.3001.5331

Java 线程演进史:从 JDK8 到 JDK21 的并发编程革命(二)https://blog.csdn.net/weixin_37549398/article/details/156042918?spm=1011.2415.3001.5331


一、引言

在 Java 并发编程中,线程是最基础的执行单元。JDK8 提供了多种创建和管理线程的方式,每种方式都有其特定的使用场景和底层实现机制。本文将全面解析 JDK8 中实现线程的方法及其底层逻辑。

二、线程实现的三种核心方式

1. 继承 Thread 类

java 复制代码
public class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println("线程执行: " + Thread.currentThread().getName());
    }
    
    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();  // 启动线程
    }
}

底层逻辑:

  • Thread 类本身实现了 Runnable 接口

  • JVM 调用 start() 方法后,会在底层创建真正的操作系统线程

  • start() 方法通过 JNI(Java Native Interface)调用操作系统原生线程创建 API

  • 线程创建完成后,JVM 调度执行 run() 方法

2. 实现 Runnable 接口(推荐方式)

java 复制代码
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Runnable执行: " + Thread.currentThread().getName());
    }
    
    public static void main(String[] args) {
        Thread thread = new Thread(new MyRunnable());
        thread.start();
    }
}

底层逻辑:

  • Runnable 是函数式接口,只定义 run() 方法

  • Thread 类接收 Runnable 实例作为执行目标

  • 避免了 Java 单继承的限制,更加灵活

  • 符合面向对象设计原则:组合优于继承

3. 实现 Callable 接口

java 复制代码
public class MyCallable implements Callable<String> {
    @Override
    public String call() throws Exception {
        return "Callable执行结果: " + Thread.currentThread().getName();
    }
    
    public static void main(String[] args) throws Exception {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<String> future = executor.submit(new MyCallable());
        System.out.println(future.get());  // 获取返回值
        executor.shutdown();
    }
}

底层逻辑:

  • Callable 允许返回结果和抛出异常

  • 通过 FutureTask 包装,实现 RunnableFuture 接口

  • ExecutorService 提交任务时,内部创建 FutureTask

  • 任务执行结果通过 Future 对象获取,支持异步编程模型

三、线程池的实现(Executor Framework)

核心线程池类型

java 复制代码
// 1. 固定大小线程池
ExecutorService fixedPool = Executors.newFixedThreadPool(5);

// 2. 缓存线程池
ExecutorService cachedPool = Executors.newCachedThreadPool();

// 3. 单线程池
ExecutorService singlePool = Executors.newSingleThreadExecutor();

// 4. 调度线程池
ScheduledExecutorService scheduledPool = Executors.newScheduledThreadPool(3);

ThreadPoolExecutor 核心原理

java 复制代码
public ThreadPoolExecutor(
    int corePoolSize,      // 核心线程数
    int maximumPoolSize,   // 最大线程数
    long keepAliveTime,    // 空闲线程存活时间
    TimeUnit unit,         // 时间单位
    BlockingQueue<Runnable> workQueue,  // 工作队列
    ThreadFactory threadFactory,        // 线程工厂
    RejectedExecutionHandler handler    // 拒绝策略
)

工作流程示意图:

java 复制代码
提交任务 → 核心线程是否满? → 否 → 创建核心线程执行
                    ↓是
           工作队列是否满? → 否 → 加入队列等待
                    ↓是
           最大线程是否满? → 否 → 创建临时线程
                    ↓是
                   执行拒绝策略

底层数据结构:

  • Worker 内部类:包装线程和任务

  • BlockingQueue:存储待执行任务(ArrayBlockingQueue、LinkedBlockingQueue 等)

  • AtomicInteger:使用 CAS 操作维护线程池状态和线程数

四、JDK8 新增特性:CompletableFuture

java 复制代码
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    System.out.println("异步执行: " + Thread.currentThread().getName());
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    return "异步计算结果";
});

底层逻辑:

  • 基于 ForkJoinPool.commonPool() 或自定义线程池

  • 实现 CompletionStage 接口,支持流式编程

  • 内部使用 Completion 链表管理依赖关系

  • 提供丰富的组合操作(thenApply、thenAccept、thenCombine 等)

五、底层线程模型详解

1. JVM 线程与操作系统线程关系

java 复制代码
Java Thread → JVM Thread → pthread(Linux)/ Windows Thread → CPU 调度
  • 1:1 模型:每个 Java 线程对应一个操作系统原生线程

  • 绿色线程(Green Threads):早期 JVM 使用的用户态线程,已弃用

  • 线程栈 :每个线程拥有独立的栈空间(默认 1MB,可通过 -Xss 调整)

2. 线程状态转换

java 复制代码
public enum State {
    NEW,           // 新建
    RUNNABLE,      // 可运行(包括就绪和运行)
    BLOCKED,       // 阻塞(等待监视器锁)
    WAITING,       // 等待(无限期等待)
    TIMED_WAITING, // 超时等待
    TERMINATED     // 终止
}

状态转换图:

java 复制代码
NEW --start()--> RUNNABLE
RUNNABLE --获取锁失败--> BLOCKED
RUNNABLE --wait()/join()--> WAITING
RUNNABLE --sleep(n)/wait(n)--> TIMED_WAITING
各种状态 --执行完毕/异常--> TERMINATED

3. 线程创建与销毁开销

创建开销:

  • 分配线程栈内存(1MB 默认)

  • 系统调用创建原生线程

  • 初始化线程本地存储(ThreadLocal)

优化建议:

  • 使用线程池复用线程

  • 合理设置线程栈大小

  • 避免频繁创建销毁线程

相关推荐
ShiJiuD6668889995 分钟前
JSP Cookie和Session
java·开发语言
geNE GENT10 分钟前
Spring Boot 实战篇(四):实现用户登录与注册功能
java·spring boot·后端
FQNmxDG4S9 小时前
Java多线程编程:Thread与Runnable的并发控制
java·开发语言
虹科网络安全9 小时前
艾体宝干货|数据复制详解:类型、原理与适用场景
java·开发语言·数据库
axng pmje10 小时前
Java语法进阶
java·开发语言·jvm
rKWP8gKv710 小时前
Java微服务性能监控:Prometheus与Grafana集成方案
java·微服务·prometheus
老前端的功夫10 小时前
【Java从入门到入土】28:Stream API:告别for循环的新时代
java·开发语言·python
qq_4352879210 小时前
第9章 夸父逐日与后羿射日:死循环与进程终止?十个太阳同时值班的并行冲突
java·开发语言·git·死循环·进程终止·并行冲突·夸父逐日
小江的记录本10 小时前
【Kafka核心】架构模型:Producer、Broker、Consumer、Consumer Group、Topic、Partition、Replica
java·数据库·分布式·后端·搜索引擎·架构·kafka
yaoxin52112310 小时前
397. Java 文件操作基础 - 创建常规文件与临时文件
java·开发语言·python