Java 环境下创建线程的标准范式
继承 Thread 基类
这是最基础的线程构建模式。开发者需要定义一个类直接派生自 java.lang.Thread 并重写其 run() 抽象方法。启动线程时,必须调用实例的 start() 方法而非直接运行 run()。底层 start() 会通过 JNI 调用操作系统原生 API 来分配新的执行栈。
class WorkerTask extends Thread {
@Override
public void run() {
String threadName = this.getName();
System.out.println(threadName + " 任务已提交至队列");
}
}
public class ThreadExtensionDemo {
public static void main(String[] args) {
WorkerTask worker = new WorkerTask();
// 启动新线程
worker.start();
}
}
实现 Runnable 接口
相较于继承类,实现 Runnable 接口更具灵活性,避免了单继承带来的层级限制。由于 Runnable 仅定义任务逻辑而无启动能力,需将其作为参数传递给 Thread 构造函数。该方式天然支持多个线程共享同一份任务资源(如变量状态)。
class SharedResource implements Runnable {
private volatile int remaining = 100;
@Override
public void execute() {
synchronized (this) {
while (remaining > 0) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("剩余数量:" + remaining--);
}
}
}
// 注意:实际 run 方法签名如下
@Override
public void run() {
while(remaining > 0) {
System.out.println("处理中,剩余:" + remaining--);
}
}
}
public class RunnableInterfaceDemo {
public static void main(String[] args) {
SharedResource job = new SharedResource();
new Thread(job, "Consumer-A").start();
new Thread(job, "Consumer-B").start();
}
}
实现 Callable 接口与 Future
当任务需要返回结果或抛出受检异常时,Runnable 不再适用,此时应使用 Callable 接口。它允许泛型指定返回值类型,配合 FutureTask 使用可以阻塞获取计算结果。此方案将异步执行与结果提取进行了分离。
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class CalculationUnit implements Callable<String> {
private final int limit;
public CalculationUnit(int n) {
this.limit = n;
}
@Override
public String call() throws Exception {
long sum = 0;
for (int i = 1; i <= limit; i++) {
sum += i;
}
return "计算结果总和为: " + sum;
}
}
public class CallableFutureDemo {
public static void main(String[] args) throws Exception {
Callable<String> taskA = new CalculationUnit(50);
FutureTask<String> future = new FutureTask<>(taskA);
new Thread(future, "Math-Processor").start();
// 等待任务完成并获取返回值
System.out.println(future.get());
}
}