线程的 run()和 start()有什么区别?

start()方法启动新线程并执行run()任务,直接调用run()只是同步执行,无法并发。

简单来说,

run()
方法是线程要执行的任务,而
start()
方法才是真正启动线程的关键。直接调用
run()
只是普通的方法调用,不会创建新的线程。

线程的

run()
start()
区别,这可是面试常考点,也是理解多线程并发的基础。

为什么不能直接调用
run()
方法?

直接调用

run()
方法,相当于在当前线程(通常是
main
线程)中执行一个普通方法。这并不会创建新的线程,也就没有并发执行的效果。所有代码都在同一个线程中顺序执行,如果
run()
方法阻塞,整个程序都会卡住。

想象一下,你在厨房做饭,

run()
方法是炒菜,
start()
方法是请了另一个厨师来帮你炒菜。如果你自己直接炒菜(调用
run()
),那还是你一个人在忙活。但如果你请了另一个厨师(调用
start()
),你们就可以同时炒不同的菜,效率大大提高。

start()
方法做了什么?

start()
方法才是启动线程的正确方式。它会执行以下几个关键步骤:

  1. 向操作系统申请创建新的线程。 这才是真正创建并发的根本。
  2. run()
    方法的调用委托给新创建的线程。
    新线程会负责执行
    run()
    方法中的代码。
  3. 线程进入就绪状态。 线程创建完成后,不会立即执行,而是等待 CPU 调度。

可以把

start()
方法想象成一个“启动器”,它负责创建新的线程,并让新线程开始执行
run()
方法中的任务。

线程池和
run()
方法的关系?

线程池是一种管理和复用线程的机制。线程池中的线程已经创建好,并等待执行任务。当我们向线程池提交任务时,线程池会选择一个空闲的线程来执行任务的

run()
方法。

线程池避免了频繁创建和销毁线程的开销,提高了程序的性能。它通过复用线程来执行不同的

run()
方法,从而实现并发执行。

举个例子,一个Web服务器使用线程池来处理客户端请求。每个客户端请求就是一个任务,服务器将任务提交给线程池,线程池中的线程会执行处理请求的代码(相当于

run()
方法)。

如何正确使用
start()
run()
方法?

  1. 永远不要直接调用
    run()
    方法。
    这是新手常犯的错误。
  2. 通过调用
    start()
    方法来启动线程。
    这是启动线程的唯一正确方式。
  3. run()
    方法中编写线程要执行的任务。
    这是线程的核心逻辑。
public class MyThread extends Thread {
    @Override
    public void run() {
        // 线程要执行的任务
        System.out.println("线程 " + Thread.currentThread().getName() + " 正在执行...");
    }

    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();

        // 启动线程
        thread1.start();
        thread2.start();
    }
}

这段代码创建了两个线程

thread1
thread2
,并通过
start()
方法启动它们。每个线程都会执行
run()
方法中的代码,打印一条消息。

为什么
run()
方法可以被重写?

run()
方法是
Thread
类中的一个方法,它可以被重写,是因为它定义了线程要执行的任务。通过重写
run()
方法,我们可以自定义线程的行为。

Thread
类本身只提供了一个默认的
run()
方法,它什么也不做。我们需要继承
Thread
类,并重写
run()
方法,才能让线程执行我们想要的任务。

线程的生命周期和
run()
方法的关系?

线程的生命周期包括以下几个状态:

  • 新建(New): 线程被创建,但尚未启动。
  • 就绪(Runnable): 线程可以被 CPU 调度执行。
  • 运行(Running): 线程正在被 CPU 执行。
  • 阻塞(Blocked): 线程因为某些原因暂停执行,例如等待 I/O 或锁。
  • 死亡(Dead): 线程执行完毕或发生异常而终止。

run()
方法的执行贯穿了线程的整个生命周期。当线程进入运行状态时,它会执行
run()
方法中的代码。当
run()
方法执行完毕或发生异常时,线程会进入死亡状态。

总而言之,理解

run()
start()
方法的区别是掌握多线程编程的关键。记住,
start()
方法负责启动线程,而
run()
方法负责定义线程要执行的任务。不要直接调用
run()
方法,而是通过
start()
方法来启动线程,才能实现真正的并发执行。