当前位置:首页 > 后端开发 > 正文

Java如何启动线程?

在Java中启动线程有两种主要方式:一是继承Thread类并重写run()方法,通过调用start()启动;二是实现Runnable接口并传入Thread构造器,再调用start(),注意直接调用run()不会创建新线程。

继承Thread类

通过继承java.lang.Thread类并重写run()方法:

class MyThread extends Thread { @Override public void run() { System.out.println("线程执行中: " + Thread.currentThread().getName()); } } // 启动线程 public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); // 正确启动方式(JVM调用run()) }

关键点

  • 调用start()而非run():start()会触发JVM创建新线程并异步执行run(),直接调用run()仅是普通方法调用(仍在主线程)。
  • 单继承限制:Java不支持多继承,若需继承其他类则无法使用此方式。


实现Runnable接口(推荐)

实现Runnable接口并重写run(),将实例传递给Thread对象:

Java如何启动线程? 第1张

优势

  • 解耦任务与线程:任务逻辑(Runnable)与线程管理(Thread)分离。
  • 避免单继承限制:可同时实现多个接口。
  • 资源复用:同一Runnable可被多个线程共享。


使用Callable和Future(带返回值)

通过Callable接口(可返回结果或抛出异常)配合线程池:

Java如何启动线程? 第2张

特点

  • 返回值支持:Callable的call()可返回结果(Runnable无返回值)。
  • 异常处理:call()允许抛出受检异常。
  • 需配合线程池使用(如ExecutorService)。


线程池(生产环境首选)

使用ExecutorService管理线程资源:

ExecutorService executor = Executors.newFixedThreadPool(4); // 创建4线程的池 // 提交Runnable任务 executor.execute(() -> { System.out.println("线程池任务"); }); // 提交Callable任务 Future<Integer> future = executor.submit(() -> 100); // 关闭线程池(需显式调用) executor.shutdown();

优势

Java如何启动线程? 第3张

  • 资源复用:减少线程创建/销毁开销。
  • 流量控制:通过池大小限制并发数。
  • 统一管理:支持任务队列、定时任务等。


Lambda表达式简化(Java 8+)

结合Lambda简化代码:

// 直接通过Thread启动 new Thread(() -> System.out.println("Lambda线程")).start(); // 线程池提交任务 ExecutorService executor = Executors.newCachedThreadPool(); executor.submit(() -> "Lambda返回值");


注意事项

  1. 线程安全
    • 共享数据需用synchronized或Lock同步。
    • 推荐使用java.util.concurrent包下的原子类(如AtomicInteger)。
  2. 资源释放
    • 线程池用后需调用shutdown(),否则进程无法终止。
  3. 避免误区
    • 不要直接调用run():它不会启动新线程。
    • 谨慎使用stop():已废弃,强制终止可能导致资源未释放。
  4. 守护线程
    • 通过setDaemon(true)设置为守护线程(JVM退出时不等待其执行完毕)。


方式 场景 优点
继承Thread 简单临时任务 代码直接
实现Runnable 需灵活性、避免单继承 解耦任务与线程(最常用)
Callable+Future 需返回值或异常处理 支持结果返回
线程池 高并发、资源敏感型应用 资源复用、性能最优(生产推荐)

实际开发中,优先选择实现Runnable接口+线程池的组合,兼顾灵活性、性能和资源管理,对于复杂异步任务,可探索CompletableFuture(Java 8+)或响应式编程框架。


引用说明

0