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)

优化建议:

  • 使用线程池复用线程

  • 合理设置线程栈大小

  • 避免频繁创建销毁线程

相关推荐
garmin Chen6 分钟前
从 Transformer 到 Agent:大模型技术全景解析
java·人工智能·python·深度学习·transformer
愚公移码12 分钟前
蓝凌EKP18产品:流程引擎技术篇之流程核心概念模型
java·人工智能·流程引擎·蓝凌
Full Stack Developme19 分钟前
Apache Tika 教程
java·开发语言·python·apache
鹅城剑仙33 分钟前
Java线程池完全指南
java
李白的天不白35 分钟前
SmartAdmin(基于 Spring Boot 框架)中配置跨域请求 VUE3 设置请求头
java·前端
橙子进阶之路37 分钟前
Java线程(CompletableFuture)
java·开发语言
鹅城剑仙1 小时前
Java CompletableFuture 异步编程完全指南
java
2601_961875241 小时前
法考备考计划表|学习计划|资料已整理
java·开发语言·学习·eclipse·tomcat·c#·hibernate
重生之我是Java开发战士1 小时前
【Java SE】多线程(三):单例模式,阻塞队列,线程池与定时器
java·javascript·单例模式
AI人工智能+电脑小能手1 小时前
【大白话说Java面试题 第115题】【并发篇】第15题:说一下悲观锁和乐观锁的区别?
java·开发语言·面试