本文目录导读:

在Java中,创建线程对象(进而启动线程)主要有三种传统方式,以及从Java 8开始引入的Lambda简化写法,以下是详细案例:
继承Thread类
这是最直接的方式,重写run()方法定义线程任务。
// 1. 定义线程类
class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 正在运行");
}
}
// 2. 使用
public class Main {
public static void main(String[] args) {
// 创建线程对象
MyThread thread1 = new MyThread();
// 启动线程(注意:是 start() 不是 run())
thread1.start();
// 也可以匿名内部类
Thread thread2 = new Thread() {
@Override
public void run() {
System.out.println("匿名线程:" + Thread.currentThread().getName());
}
};
thread2.start();
}
}
实现Runnable接口
更推荐的方式,因为Java是单继承,接口更灵活。
// 1. 定义任务类
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " 正在运行");
}
}
// 2. 使用
public class Main {
public static void main(String[] args) {
// 创建Runnable对象
MyRunnable task = new MyRunnable();
// 创建线程对象(传入Runnable)
Thread thread = new Thread(task);
thread.start();
// Lambda简化(Java 8+)
Thread thread2 = new Thread(() -> {
System.out.println("Lambda线程:" + Thread.currentThread().getName());
});
thread2.start();
}
}
实现Callable接口 + FutureTask(带返回值)
当线程需要返回结果时使用。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
// 1. 定义Callable任务
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
System.out.println(Thread.currentThread().getName() + " 正在计算");
Thread.sleep(1000);
return "计算结果:100";
}
}
// 2. 使用
public class Main {
public static void main(String[] args) throws Exception {
// 创建Callable任务
MyCallable callable = new MyCallable();
// 包装成FutureTask(它也实现了Runnable)
FutureTask<String> futureTask = new FutureTask<>(callable);
// 创建线程对象
Thread thread = new Thread(futureTask);
thread.start();
// 获取返回结果(会阻塞等待线程完成)
String result = futureTask.get();
System.out.println("获取到结果:" + result);
}
}
使用线程池(推荐用于生产环境)
虽然本质上也是基于以上方式,但更高效、可控。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
// 创建线程池
ExecutorService executor = Executors.newFixedThreadPool(3);
// 提交任务(自动创建线程对象并运行)
executor.submit(() -> {
System.out.println("线程池任务1:" + Thread.currentThread().getName());
});
executor.submit(new Runnable() {
@Override
public void run() {
System.out.println("线程池任务2:" + Thread.currentThread().getName());
}
});
// 关闭线程池
executor.shutdown();
}
}
| 方式 | 是否需要继承类 | 能否返回结果 | 推荐度 |
|---|---|---|---|
| 继承Thread | 是(占用继承) | 否 | ❌ 不推荐 |
| 实现Runnable | 否 | 否 | ✅ 推荐 |
| 实现Callable | 否 | 是 | ✅ 有返回值的场景 |
| Lambda/Runnable | 否 | 否 | ✅ 最简洁 |
常见错误
// 错误:直接调用run()不是启动新线程,而是在当前线程运行 thread.run(); // 这是普通方法调用,不会启动新线程 // 正确:必须调用start() thread.start(); // 启动新线程,JVM自动调用run()
最佳实践:日常开发优先使用 Runnable + Lambda(简洁),需要返回值用 Callable + FutureTask,高并发场景用 线程池。