一句话说透Java里面的创建线程的三种方式

161 阅读2分钟

线程就像公司里的工人,负责执行具体的任务。Java 中创建线程的三种方式,本质是 让工人知道要干什么活。以下用最直白的方式解释:


1. 继承 Thread 类:直接当工人

步骤

  1. 写一个类继承 Thread
  2. 重写 run() 方法(定义任务内容)
  3. 调用 start() 启动线程

代码示例

class MyThread extends Thread {  
    @Override  
    public void run() {  
        System.out.println("我是继承Thread的线程!");  
    }  
}  

public class Main {  
    public static void main(String[] args) {  
        MyThread thread = new MyThread();  
        thread.start(); // 启动线程  
    }  
}  

缺点

  • 单继承限制:Java 只能单继承,如果类已经继承了其他类,就不能用这种方式了。
  • 代码耦合:任务和线程绑定,不够灵活。

2. 实现 Runnable 接口:让工人拿任务单

步骤

  1. 写一个类实现 Runnable
  2. 实现 run() 方法(定义任务内容)
  3. 把任务交给 Thread 执行

代码示例

class MyTask implements Runnable {  
    @Override  
    public void run() {  
        System.out.println("我是实现Runnable的线程!");  
    }  
}  

public class Main {  
    public static void main(String[] args) {  
        Thread thread = new Thread(new MyTask());  
        thread.start();  
    }  
}  

优点

  • 解耦:任务(Runnable)和线程(Thread)分离,更灵活。
  • 支持多实现:可以同时实现多个接口。

3. 实现 Callable 接口:要汇报结果的工人

特点

  • 和 Runnable 类似,但任务可以有返回值,还能抛异常。
  • 需要配合 FutureTask 或线程池使用。

代码示例

import java.util.concurrent.Callable;  
import java.util.concurrent.FutureTask;  

class MyCallableTask implements Callable<String> {  
    @Override  
    public String call() throws Exception {  
        return "我是Callable线程,我有返回值!";  
    }  
}  

public class Main {  
    public static void main(String[] args) throws Exception {  
        FutureTask<String> futureTask = new FutureTask<>(new MyCallableTask());  
        Thread thread = new Thread(futureTask);  
        thread.start();  
        System.out.println(futureTask.get()); // 获取返回值  
    }  
}  

优点

  • 能返回结果:适合需要获取任务执行结果的场景。
  • 异常处理:任务中可以抛出异常,由主线程捕获。

三种方式对比

方式优点缺点适用场景
继承 Thread简单直接单继承限制,耦合高简单测试、临时任务
实现 Runnable灵活解耦,可复用无返回值大多数多线程场景
实现 Callable支持返回值和异常需配合 FutureTask 使用需要结果或异常处理的场景

实际开发建议

  1. 优先用 Runnable:灵活、解耦,适合大部分场景。
  2. 需要返回值时用 Callable:比如异步计算、批量处理任务。
  3. 别直接继承 Thread:除非需要重写 Thread 的其他方法(但这种情况很少)。

附:线程池才是终极答案!

实际项目中,一般不会直接 new Thread(),而是用 线程池 管理线程,避免频繁创建销毁线程的开销。

// 使用线程池执行 Runnable  
ExecutorService executor = Executors.newFixedThreadPool(5);  
executor.execute(new MyTask());  

总结口诀
「创建线程三方式,继承Thread最简单
Runnable更灵活,Callable能返结果
实际开发用池管,性能稳定不翻车!」