Z
ZHANK
编程在线教程Java 教程线程的创建与运行
多线程

线程的创建与运行

掌握 Thread、Runnable、Callable、线程状态与生命周期

线程的创建与运行

你的程序默认只有一个"主线程"在跑。多线程就是同时开启多条执行路径,比如一边下载文件一边更新进度条。但多线程也带来竞态条件、死锁等复杂问题——所以理解基础原理至关重要。

学完本章你将: 掌握三种创建线程方式、线程状态、常用控制方法。


创建线程的三种方式

Java 中启动一个新线程,本质上是把一段代码(run() 方法)交给 JVM 的线程调度器去执行。关键在于:调用 start() 才会创建新线程,直接调用 run() 只是普通方法调用。

java
// 方式 1:继承 Thread(简单但不灵活——Java 单继承,不能再继承其他类)
class MyThread extends Thread {
    @Override
    public void run() {
        System.out.println(getName() + " 执行中"); // getName() 获取线程名
    }
}
new MyThread().start(); // ✅ 新线程执行 run()
// new MyThread().run(); // ❌ 当前线程执行,不是多线程!
java
// 方式 2:实现 Runnable(推荐——任务和线程分离,还能继承其他类)
class MyTask implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + " 执行");
    }
}
Thread t = new Thread(new MyTask(), "Worker-1"); // 起个名字方便调试
t.start();
java
// 方式 3:Callable + Future(有返回值,能抛异常)
Callable<Integer> task = () -> {
    Thread.sleep(1000);  // 模拟耗时操作
    return 42;           // 返回计算结果
};
FutureTask<Integer> future = new FutureTask<>(task);
new Thread(future).start();
System.out.println("结果:" + future.get()); // get() 阻塞等待,拿到 42 后才继续
方式有返回值能抛异常推荐度
Thread简单场景
Runnable⭐ 日常首选
Callable需要结果时用

Lambda 简化写法

java
// Runnable — 一行搞定
new Thread(() -> System.out.println("Hello!")).start();

// Callable + 线程池(不直接 new Thread)
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<String> result = pool.submit(() -> "任务完成");
System.out.println(result.get());
pool.shutdown(); // 别忘了关闭线程池

线程状态 —— 生命周期

        ┌─ NEW(刚创建,还没 start)
        ↓
   RUNNABLE(运行中 / 等待 CPU)
   ↙      ↓       ↘
BLOCKED  WAITING  TIMED_WAITING(各种等待状态)
   ↘      ↓       ↙
     TERMINATED(执行完毕)
java
Thread t = new Thread(() -> {});  // NEW
t.start();                        // RUNNABLE
t.join();                         // 等 t 结束
System.out.println(t.getState()); // TERMINATED

💡 RUNNABLE 不等于"正在运行"。 它只是"可运行"——可能在跑,也可能在排队等 CPU。具体由操作系统调度,你控制不了。


常用控制方法

java
Thread.sleep(1000);        // 让当前线程暂停 1 秒(不释放锁!)
t.join();                  // 等待线程 t 执行完毕再继续
t.setPriority(Thread.MAX_PRIORITY); // 设优先级(1~10,只是建议,不保证)
t.setDaemon(true);         // 设为守护线程:主线程结束,守护线程自动终止
Thread.yield();             // 主动让出 CPU(只是建议,JVM 可能忽略)

⚠️ 守护线程注意: GC 就是典型的守护线程。如果你把重要业务线程设为守护线程,一旦主线程结束它就被强制终止——可能数据写到一半就没了。