Java 线程实现方式

1. Java 线程概述

1.1 映射模型

Java 线程采用1:1映射到操作系统原生线程(内核级线程),线程是程序执行的一个路径,每一个钱程都有自己的局部变量表、程序计数器以及各自的生命周期等。在 JVM 中:

  • java.lang.Thread对象是Java层的线程抽象
  • 底层通过pthread_create(Linux)或CreateThread(Windows)创建系统线程
  • 线程调度由操作系统内核直接管理(抢占式调度,时间片)
sequenceDiagram CPU->> +线程A: 执行中 CPU-->> 操作系统: 时钟中断 操作系统->> CPU: 保存线程A寄存器状态 CPU->> 线程B: 加载线程B寄存器状态 CPU->> +线程B: 继续执行

1.2 Java 多线程

现代操作系统中一般不止一个线程在运行,当启动了一个 Java 虚拟机时,从操作系统开始就会创建一个新的进程( JVM 进程),JVM 进程中将会派生或者创建很多线程,可以说 java 中的程序天生就是多线程:

java 复制代码
// JDK 21
public class Test {
    public static void main(String[] args) {
        // Java 虚拟机线程系统的管理接口
        ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
        // 获取线程和线程堆栈信息
        ThreadInfo[] threadInfos = threadMXBean.dumpAllThreads(false, false);
        for (ThreadInfo threadInfo :
                threadInfos) {
            System.out.println("[" + threadInfo.getThreadId() + "] " + threadInfo.getThreadName());
        }
    }
}

Java ThreadMXBean 是 Java Management Extensions(JMX)API 中的一个接口,用于管理和监控Java虚拟机的线程系统。

运行结果:

在 android 中可以使用以下代码打印:

java 复制代码
public static void logAllThreads() {
    try {
        ThreadGroup group = Thread.currentThread().getThreadGroup();

        // 遍历到最顶层的线程组
        while (group.getParent() != null) {
            group = group.getParent();
        }

        // 获取线程组中的线程数量
        int threadCount = group.activeCount();
        Thread[] threads = new Thread[threadCount];
        group.enumerate(threads);

        // 打印线程信息
        for (Thread thread : threads) {
            Log.i("ThreadInfo" + "[" + thread.getId() + "] " + thread.getName());
        }
    } catch (Exception e) {
        Log.i("ThreadInfo" + "Error enumerating threads", e);
    }
}

1.3 Java 线程状态

Java 线程状态在 Thread.State 中明确定义:

状态 触发条件 操作系统映射
NEW Thread实例化后,start()前 未创建系统线程
RUNNABLE start()调用后 就绪/运行状态
BLOCKED 竞争synchronized锁失败 内核阻塞状态
WAITING wait()/join()/park()调用 内核休眠+条件等待
TIMED_WAITING sleep(n)/wait(n)等超时方法 内核定时休眠
TERMINATED run()执行结束 线程资源已回收

关键差异:Java的RUNNABLE状态对应操作系统的就绪(Ready)和运行(Running)两种状态

2. 多线程的实现方式

java 1.8 中写到,创建线程有两种方式。There are two ways to create a new thread of execution.

2.1 继承 Thread 类并实现 run 方法

声明一个 Thread 的子类,此子类应重写 Thread 类的 run 方法。

java 复制代码
class PrimeThread extends Thread {
   long minPrime;
   PrimeThread(long minPrime) {
       this.minPrime = minPrime;
   }

   public void run() {
       // compute primes larger than minPrime
       . . .
   }
}

创建一个实例并运行:

java 复制代码
PrimeThread p = new PrimeThread(143);
p.start();

优点:

  1. 编程比较简单
  2. 可以直接使用 Thread 类中的方法

缺点:

  1. 可扩展性差,耦合度高,不能再继承其他的类
  2. run 方法没有返回值,不能获取返回结果

2.2 声明一个实现 Runnable 接口的类并实现 run() 方法

Thread:对线程的抽象。

Runnable:对线程中任务、业务逻辑的抽象

Runnable 接口: 只有一个 run() 方法,当使用 Runnable 接口创建Thread 实例时,run() 方法被调用,该方法为线程执行的起点。

java 复制代码
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

扩展性强,实现接口还可以继承其他类。

java 复制代码
class PrimeRun implements Runnable {
   long minPrime;
   PrimeRun(long minPrime) {
       this.minPrime = minPrime;
   }

   public void run() {
       // compute primes larger than minPrime
        . . .
   }
}

创建一个实例并运行:

java 复制代码
PrimeRun p = new PrimeRun(143);
new Thread(p).start();

使用内部类:

java 复制代码
new Thread(new Runnable(){
    @Override
    public void run(){
        //处理具体的逻辑
    }
}).start();

优点:

  1. 实现接口还可以继承其他类
  2. 任务与线程解耦,支持线程池
  3. 策略模式的应用(点击阅读:策略模式

缺点:

  1. run 方法没有返回值,不能获取返回结果。

2.3 利用 Callable 接口和 Future 接口方式实现

除了官方注释中给出的方法,我们还可以通过以下几种方法实现 java 线程。

实现 Callable 接口可以获取到多线程运行的结果。

java 复制代码
public class MyCallable implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        int sum = 0;
        for (int i = 0; i < 100; i++) {
            sum = sum + i;
        }
        return sum;
    }
}

//创建MyCallable对象(线程要执行的任务)
MyCallable mc = new MyCallable();
//创建FutureTask对象(管理多线程运行的结果)
FutureTask<Integer> ft = new FutureTask<>(mc);
Thread thread = new Thread(ft);
thread.start();
//获取多线程运行的结果
Integer result = ft.get();
System.out.println(result);
classDiagram RunnableFuture <|-- FutureTask Callable --> FutureTask : 任务适配 FutureTask --> Thread : 执行载体

优点:

  1. 支持返回值与异常传播
java 复制代码
FutureTask task = new FutureTask(() -> {
    if(error) throw new IOException("模拟错误");
    return 42;
});

new Thread(task).start();

try {
    Integer result = task.get(); // 阻塞获取结果
} catch (ExecutionException e) {
    Throwable cause = e.getCause(); // 获取原始异常
    System.out.println("业务异常: " + cause.getMessage());
}

2.4 线程池

java 复制代码
ExecutorService pool = Executors.newVirtualThreadPerTaskExecutor(); // JDK21虚拟线程池
// Executors.newFixedThreadPool(10); // 传统固定池

pool.submit(() -> {
    System.out.println(Thread.currentThread().getName());
});

核心优势

  1. 降低线程创建销毁开销(线程复用)
  2. 提供队列缓冲(避免资源耗尽)
  3. 支持定时/周期任务

2.5 java21 中创建线程的方式

java 复制代码
// Start a daemon thread to run a task
Thread thread = Thread.ofPlatform().daemon().start(runnable);

// Create an unstarted thread with name "duke", its start() method
// must be invoked to schedule it to execute.
Thread thread = Thread.ofPlatform().name("duke").unstarted(runnable);

// A ThreadFactory that creates daemon threads named "worker-0", "worker-1", ...
ThreadFactory factory = Thread.ofPlatform().daemon().name("worker-", 0).factory();

// Start a virtual thread to run a task
Thread thread = Thread.ofVirtual().start(runnable);

// A ThreadFactory that creates virtual threads
ThreadFactory factory = Thread.ofVirtual().factory();

2.6 总结

方式 代码示例 优势 劣势 原理
继承Thread class MyThread extends Thread { run(){...} } 直接访问线程方法 破坏单一继承原则 创建OS线程绑定Java线程对象
实现Runnable new Thread(() -> {...}).start() 任务线程解耦 无返回值 策略模式:Thread组合Runnable
Callable+Future FutureTask task = new FutureTask(callable); new Thread(task).start() 支持返回值/异常 编码较复杂 FutureTask实现RunnableFuture接口
线程池提交 executor.submit(() -> { return 42; }) 资源复用/管理 需关闭线程池 线程复用+任务队列管理

本文简单描述一下 Java 线程的创建方式,后会不断深入分析补充

相关推荐
芷栀夏28 分钟前
飞算Java AI开发助手:引领智能编程新风尚
java·人工智能·python
刺客xs28 分钟前
MYSQL数据库----DCL语句
android·数据库·mysql
iReaShare32 分钟前
如何将数据从一部手机传输到另一部手机?
android
Moso_Rx36 分钟前
JavaEE多线程——锁策略 CAS synchronized优化
java·java-ee
Dcs40 分钟前
他花了一千美元买AI写代码,却说“值了”:深入解析大型思维模型的开发效率革命
java
Hello-Mr.Wang43 分钟前
使用Spring Boot和PageHelper实现数据分页
java·开发语言·spring boot
慢行的骑兵1 小时前
Android音视频探索之旅 | C++层使用OpenGL ES实现视频渲染
android·音视频·ndk
佩奇大王1 小时前
java 接口
java·开发语言
iReaShare1 小时前
将CSV联系人导入安卓手机的3种简单方法
android
DKPT1 小时前
Java设计模式之行为型模式(命令模式)介绍与说明
java·笔记·学习·设计模式