Java多线程(一):多线程的三种创建方式
在现代软件开发中,多线程编程是提升程序性能、实现并发处理的核心技术之一。Java 从诞生之初就对多线程提供了强大的支持,使得开发者可以轻松地编写并发程序。本文将详细介绍 Java 中创建多线程的三种经典方式:继承 Thread
类、实现 Runnable
接口,以及实现 Callable
接口。
一、继承 Thread 类
最直观的创建线程方式是通过继承 java.lang.Thread
类,并重写其 run()
方法。当调用线程的 start()
方法时,JVM 会自动调用 run()
方法来执行线程的任务。
示例代码:
import java.util.Random;
public class MyThread extends Thread {
private static final Random RANDOM = new Random();
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(getName() + " : " + i);
try {
// 模拟任务执行时间,随机休眠0~100毫秒
Thread.sleep(RANDOM.nextInt(100));
} catch (InterruptedException e) {
System.out.println(getName() + " 被中断");
Thread.currentThread().interrupt(); // 恢复中断状态
}
}
}
}
// 测试类
public class ThreadCreationDemo {
public static void main(String[] args) {
System.out.println("主线程启动");
// 创建并启动3个线程
for (int i = 0; i < 3; i++) {
new MyThread().start();
}
System.out.println("主线程结束");
}
}
说明:
getName()
获取线程名称(默认为Thread-0
,Thread-1
等)。Thread.sleep()
用于模拟耗时操作。- 注意捕获
InterruptedException
并处理中断状态。
⚠️ 缺点:由于 Java 不支持多继承,继承
Thread
类后无法再继承其他类,灵活性较差。
二、实现 Runnable 接口
更推荐的方式是实现 java.lang.Runnable
接口。Runnable
只定义了一个 run()
方法,表示可执行的任务。通过将 Runnable
实例传递给 Thread
构造函数来创建线程。
示例代码(使用 Lambda 表达式):
import java.util.Random;
public class RunnableDemo {
public static void main(String[] args) {
System.out.println("主线程启动");
// 使用 Lambda 表达式创建 Runnable 任务
Runnable task = () -> {
Random random = new Random();
String threadName = Thread.currentThread().getName();
for (int i = 0; i < 10; i++) {
System.out.println(threadName + " : " + i);
try {
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
System.out.println(threadName + " 被中断");
Thread.currentThread().interrupt();
}
}
};
// 创建3个线程并启动
for (int i = 0; i < 3; i++) {
new Thread(task).start();
}
System.out.println("主线程结束");
}
}
说明:
- 使用 Lambda 表达式使代码更简洁。
- 多个线程可以共享同一个
Runnable
实例,适合任务相同但需并发执行的场景。 - 解耦了任务与线程,提高了代码的灵活性和可复用性。
✅ 推荐使用:这是最常用的多线程创建方式。
三、实现 Callable 接口
Callable
接口与 Runnable
类似,但功能更强大。它允许任务返回结果,并可以抛出受检异常。Callable
通常配合 FutureTask
使用。
示例代码:
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableDemo {
public static void main(String[] args) {
System.out.println("主线程启动");
Random random = new Random();
for (int i = 0; i < 3; i++) {
// 创建 Callable 任务:返回一个0~9之间的随机整数
Callable<Integer> task = () -> {
int result = random.nextInt(10);
System.out.println(Thread.currentThread().getName() + " 生成了: " + result);
return result;
};
// 将 Callable 包装为 FutureTask
FutureTask<Integer> futureTask = new FutureTask<>(task);
// 创建线程并启动
new Thread(futureTask).start();
try {
// 获取任务执行结果(阻塞直到结果可用)
Integer result = futureTask.get();
System.out.println("获取到结果: " + result);
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("主线程结束");
}
}
说明:
Callable<V>
的call()
方法有返回值(类型为V
),且可抛出异常。FutureTask
是Future
接口的实现类,用于获取异步计算结果。futureTask.get()
会阻塞当前线程,直到任务完成并返回结果。
✅ 适用场景:需要获取线程执行结果或处理异常时使用。
三种方式对比
方式 | 是否有返回值 | 是否可抛异常 | 推荐程度 | 说明 |
---|---|---|---|---|
继承 Thread | ❌ 否 | ❌ 否 | ⭐ | 简单但不灵活 |
实现 Runnable | ❌ 否 | ❌ 否 | ⭐⭐⭐⭐ | 最常用,推荐 |
实现 Callable | ✅ 是 | ✅ 是 | ⭐⭐⭐⭐ | 需要结果时使用 |
总结
本文介绍了 Java 多线程的三种创建方式:
- 继承
Thread
类:简单直观,但不推荐。 - 实现
Runnable
接口:解耦任务与线程,推荐使用。 - 实现
Callable
接口:可获取返回值,适用于需要结果的场景。
在实际开发中,建议优先使用 Runnable
或 Callable
,避免继承 Thread
类。随着 Java 并发工具类(如线程池 ExecutorService
)的发展,直接创建线程的方式已逐渐被更高级的抽象所取代,但理解这三种基础方式仍是掌握 Java 多线程的基石。
本文是原创文章,完整转载请注明来自 小希的网站
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果