在 Java 中,创建线程主要有以下几种方式。下面我将详细解释每种方式,并提供代码示例。

1. 继承 Thread 类

这是最基础的创建线程方式,通过继承 Thread 类并重写 run() 方法。

public class MyThread extends Thread {

@Override

public void run() {

System.out.println("线程运行中: " + Thread.currentThread().getName());

}

}

// 使用方式

public class Main {

public static void main(String[] args) {

MyThread thread = new MyThread();

thread.start(); // 启动线程

}

}

特点:

简单直接由于 Java 是单继承,这种方式会占用继承位置线程与任务耦合在一起

2. 实现 Runnable 接口

更常用的方式是实现 Runnable 接口,将线程和任务解耦。

public class MyRunnable implements Runnable {

@Override

public void run() {

System.out.println("线程运行中: " + Thread.currentThread().getName());

}

}

// 使用方式

public class Main {

public static void main(String[] args) {

Thread thread = new Thread(new MyRunnable());

thread.start();

// 或者使用 Lambda 表达式(Java 8+)

Thread lambdaThread = new Thread(() -> {

System.out.println("Lambda 线程运行中: " + Thread.currentThread().getName());

});

lambdaThread.start();

}

}

特点:

推荐使用的方式线程与任务分离,更灵活可以实现多个接口,不影响类继承结构

3. 实现 Callable 接口

Callable 与 Runnable 类似,但可以返回结果和抛出异常。

import java.util.concurrent.Callable;

import java.util.concurrent.FutureTask;

public class MyCallable implements Callable {

@Override

public String call() throws Exception {

Thread.sleep(1000); // 模拟耗时操作

return "任务执行完成: " + Thread.currentThread().getName();

}

}

// 使用方式

public class Main {

public static void main(String[] args) throws Exception {

FutureTask futureTask = new FutureTask<>(new MyCallable());

Thread thread = new Thread(futureTask);

thread.start();

// 获取执行结果(会阻塞直到任务完成)

String result = futureTask.get();

System.out.println(result);

}

}

特点:

可以返回执行结果可以抛出异常需要配合 FutureTask 或线程池使用

4. 使用线程池(ExecutorService)

在实际开发中,最推荐使用线程池来管理线程,提高资源利用率。

import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;

import java.util.concurrent.TimeUnit;

public class ThreadPoolExample {

public static void main(String[] args) {

// 创建固定大小的线程池

ExecutorService executor = Executors.newFixedThreadPool(3);

// 提交任务

for (int i = 0; i < 5; i++) {

final int taskId = i;

executor.submit(() -> {

System.out.println("任务 " + taskId + " 执行中: " + Thread.currentThread().getName());

try {

TimeUnit.MILLISECONDS.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

});

}

// 关闭线程池

executor.shutdown();

try {

// 等待所有任务完成

if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {

executor.shutdownNow();

}

} catch (InterruptedException e) {

executor.shutdownNow();

}

}

}

特点:

管理和复用线程,减少创建销毁开销控制并发线程数量提供任务队列、定时执行等功能

5. 使用 CompletableFuture (Java 8+)

Java 8 引入的 CompletableFuture 提供了更强大的异步编程能力。

import java.util.concurrent.CompletableFuture;

import java.util.concurrent.ExecutionException;

public class CompletableFutureExample {

public static void main(String[] args) throws ExecutionException, InterruptedException {

// 创建异步任务

CompletableFuture future = CompletableFuture.supplyAsync(() -> {

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

return "异步任务结果";

});

// 处理任务结果

future.thenAccept(result -> {

System.out.println("处理结果: " + result);

});

// 等待任务完成

future.get();

}

}

6. 使用 Spring 的 @Async 注解

在 Spring 框架中,可以使用 @Async 注解轻松创建异步方法。

import org.springframework.scheduling.annotation.Async;

import org.springframework.scheduling.annotation.EnableAsync;

import org.springframework.stereotype.Component;

@EnableAsync

@Component

public class AsyncService {

@Async

public void asyncMethod() {

System.out.println("异步方法执行: " + Thread.currentThread().getName());

}

}

// 在 Controller 或 Service 中调用

asyncService.asyncMethod();

对比总结

创建方式优点缺点适用场景继承 Thread简单直接占用继承位置,耦合度高简单测试或demo实现 Runnable灵活,解耦不能直接返回结果大多数场景实现 Callable可返回结果,可抛异常使用稍复杂需要返回结果的异步任务线程池资源复用,功能强大配置稍复杂生产环境,高并发场景CompletableFuture功能强大,链式编程Java 8+ 支持复杂异步编程Spring @Async集成简单,注解驱动需要 Spring 环境Spring 项目中的异步处理最佳实践建议

优先使用线程池而不是直接创建线程,避免资源浪费实现 Runnable 接口比继承 Thread 类更灵活需要返回值时使用 Callable 和 Future在 Spring 项目中使用 @Async 注解简化异步编程对于复杂异步流程,使用 CompletableFuture始终处理线程中的异常,避免 silent failure

// 异常处理示例

Thread thread = new Thread(() -> {

try {

// 任务代码

} catch (Exception e) {

System.err.println("线程执行异常: " + e.getMessage());

}

});

thread.setUncaughtExceptionHandler((t, e) -> {

System.err.println("线程 " + t.getName() + " 发生异常: " + e.getMessage());

});

thread.start();

根据具体需求选择合适的线程创建方式,可以提高代码的可维护性和性能。