首页...Java多线程基础与线程的创建与管理
Java语言程序设计第六章 多线程与并发/第二节

Java多线程基础与线程的创建与管理

2026-03-24

第六章 多线程与并发

第二节 Java多线程基础与线程的创建与管理

概述

本节内容聚焦于Java多线程编程的基础知识,重点讲解线程的创建、启动、执行及生命周期管理。掌握本节内容,有助于考生理解多线程的基本原理和Java中线程的具体实现方法,同时为后续深入学习线程同步与并发控制打下坚实基础。

学习目标

  • 理解线程的概念及其重要性
  • 掌握Java中创建线程的两种主要方式
  • 理解线程的生命周期及状态转换
  • 学习线程的基本管理操作,如启动、休眠、终止
  • 通过实例掌握线程的实际应用

核心概念

线程(Thread)

线程是程序执行的最小单位,是进程中的一个执行流。Java中的多线程允许程序同时执行多个任务,提高程序响应能力和资源利用率。

进程(Process)

进程是操作系统分配资源的基本单位,一个进程中可以包含多个线程。

线程的生命周期

线程从创建到终止经历多个状态:新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)、等待(Waiting)、计时等待(Timed Waiting)、终止(Terminated)。

线程调度

线程调度是操作系统或Java虚拟机决定哪个线程获得CPU执行权的过程,Java线程调度基于优先级和时间片轮转。

线程安全

指多线程环境下,多个线程访问共享资源时能够保证数据的一致性和正确性。


原理分析

Java的多线程机制基于Java.lang.Thread类和Runnable接口。

  • Thread类代表一个线程对象,直接继承Thread类可以创建线程。
  • Runnable接口定义了线程执行任务的规范,适合多个线程共享同一任务。

线程生命周期管理依赖于操作系统线程调度,Java线程状态转移是通过线程API和JVM实现的。线程启动后由操作系统调度分配CPU时间片,线程执行run()方法体内的代码。

线程切换是CPU在不同线程间快速切换执行权,虽然提高了程序响应性,但频繁切换带来上下文切换开销。


详细内容

1. 线程的创建方式

Java中创建线程的两种主要方式:

  • 继承Thread类

    1. 定义一个继承Thread的子类,重写run()方法。
    2. 创建该子类的实例。
    3. 调用start()方法启动线程。

示例代码:

class MyThread extends Thread {
    public void run() {
        System.out.println("线程运行中:" + Thread.currentThread().getName());
    }
}

public class TestThread {
    public static void main(String[] args) {
        MyThread t = new MyThread();
        t.start(); // 启动线程
    }
}
  • 实现Runnable接口

    1. 定义一个实现Runnable接口的类,实现run()方法。
    2. 创建该类对象。
    3. 使用Thread类构造函数传入Runnable对象,创建线程。
    4. 调用start()方法启动线程。

示例代码:

class MyRunnable implements Runnable {
    public void run() {
        System.out.println("线程运行中:" + Thread.currentThread().getName());
    }
}

public class TestRunnable {
    public static void main(String[] args) {
        Thread t = new Thread(new MyRunnable());
        t.start();
    }
}

区别与选择

继承Thread类 实现Runnable接口
单继承限制,不能继承其他类 可以继承其他类,灵活性高
线程对象即任务对象 线程对象和任务对象分离,有利资源共享
适合简单线程任务 更适合复杂任务与线程共享

2. 线程的生命周期及状态转换

线程状态包括:

  • 新建状态(New):线程对象被创建,但尚未启动。
  • 就绪状态(Runnable):调用start()后线程处于就绪,等待CPU分配时间。
  • 运行状态(Running):线程获得CPU时间片,执行run()方法。
  • 阻塞状态(Blocked):线程等待获取监视器锁,无法执行。
  • 等待状态(Waiting):线程无限期等待其他线程通知。
  • 计时等待(Timed Waiting):线程等待指定时间后自动恢复。
  • 终止状态(Terminated):线程执行完毕或异常结束。

线程状态转换图示:

  • 新建 -> 就绪:调用start()
  • 就绪 -> 运行:线程调度
  • 运行 -> 阻塞:等待锁
  • 运行 -> 等待:调用wait()
  • 运行 -> 计时等待:调用sleep(), join(timeout)
  • 阻塞/等待/计时等待 -> 就绪:锁释放或等待结束
  • 运行 -> 终止:run()执行完成或异常

3. 线程的基本操作

  • start():启动线程,进入就绪状态。
  • run():线程执行体,建议不要直接调用run(),否则成为普通方法调用。
  • sleep(long millis):使线程暂停指定毫秒,进入计时等待。
  • yield():线程让出CPU,进入就绪状态,等待重新调度。
  • join():等待线程执行完毕。
  • interrupt():中断线程,设置中断标志。

4. 线程优先级

Java线程优先级范围为1(最低)到10(最高),默认优先级是5。

线程调度器优先选择优先级高的线程执行,但优先级不是绝对保证,依赖于操作系统。

5. 线程安全与同步基础(预备知识)

多线程访问共享资源可能导致数据不一致,线程安全问题由此产生。Java提供了synchronized关键字和Lock接口实现线程同步,这将在后续章节详细讲解。


实例分析

实例1:继承Thread类创建线程

背景:实现一个简单线程,输出线程名称。

代码

class MyThread extends Thread {
    public void run() {
        for(int i=0; i<5; i++) {
            System.out.println(Thread.currentThread().getName() + "运行第" + i + "次");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                System.out.println("线程被中断");
            }
        }
    }
}

public class TestThread {
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        t1.start();
        t2.start();
    }
}

分析

  • 创建两个线程对象t1和t2
  • 分别调用start()启动线程
  • 两个线程交替运行,输出各自名称和计数
  • 使用sleep暂停线程,模拟实际工作

结论:继承Thread类简单直接,适合初学者理解线程基本概念。

实例2:实现Runnable接口创建线程

背景:多个线程执行同一个任务,模拟售票场景。

代码

class TicketWindow implements Runnable {
    private int tickets = 5;

    public void run() {
        while(tickets > 0) {
            System.out.println(Thread.currentThread().getName() + "卖票,余票:" + tickets);
            tickets--;
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {}
        }
    }
}

public class TestRunnable {
    public static void main(String[] args) {
        TicketWindow window = new TicketWindow();
        Thread t1 = new Thread(window, "窗口1");
        Thread t2 = new Thread(window, "窗口2");
        t1.start();
        t2.start();
    }
}

分析

  • TicketWindow实现Runnable,定义共享票数变量
  • 两个线程共享同一Runnable对象,模拟售票窗口
  • 可能出现线程安全问题(票数错误)

结论:Runnable方式适合多个线程共享任务对象,利于资源共享与管理。

实例3:线程状态演示

背景:演示线程的不同状态转换。

代码

public class ThreadStateDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            try {
                Thread.sleep(1000); // TIMED_WAITING
            } catch (InterruptedException e) {}
        });

        System.out.println("新建状态: " + t.getState()); // NEW
        t.start();
        Thread.sleep(100); // 等待线程启动
        System.out.println("运行或就绪状态: " + t.getState()); // RUNNABLE
        Thread.sleep(1100);
        System.out.println("终止状态: " + t.getState()); // TERMINATED
    }
}

分析

  • 观察线程在不同时间点的状态
  • 通过sleep模拟计时等待状态

结论:线程状态可通过getState()方法查看,理解状态有助于调试和设计多线程程序。


常见误区与注意事项

  1. 直接调用run()方法启动线程

    • 错误:直接调用run()方法不会启动新线程,而是当前线程顺序执行。
    • 正确:调用start()方法启动线程。
  2. 线程启动后重复调用start()

    • 错误:同一个线程对象start()只能调用一次,再次调用抛出IllegalThreadStateException。
  3. 忽视线程安全问题

    • 多线程共享资源时未同步,导致数据不一致。
    • 需使用同步机制保证安全。
  4. 对线程优先级理解错误

    • 优先级高的线程不一定先执行,线程调度受操作系统影响。
  5. 忽略异常处理

    • sleep()和join()等方法会抛出InterruptedException,必须捕获或声明抛出。

应用场景

  • 多任务并行处理:如同时下载多个文件,提高效率。
  • 界面响应性:UI线程负责界面显示,后台线程处理耗时操作,避免界面卡死。
  • 服务器并发请求处理:每个请求启动独立线程处理,提升并发能力。
  • 定时任务执行:使用线程定时执行任务,如日志清理。
  • 资源共享协调:多个线程协作完成复杂任务。

知识拓展

  • 线程同步与锁机制:synchronized关键字、Lock接口
  • 线程通信:wait(), notify(), notifyAll()方法
  • 线程池:Executor框架管理线程资源,提高性能
  • 并发工具类:CountDownLatch, CyclicBarrier, Semaphore等
  • 线程安全集合:ConcurrentHashMap等

总结回顾

本节重点介绍了Java多线程编程的基础知识,重点内容包括:

  • 线程的定义与重要性
  • 线程的两种创建方式:继承Thread类与实现Runnable接口
  • 线程生命周期及状态转换
  • 线程的基本管理操作,如启动、休眠、中断
  • 线程优先级的基本概念

通过典型实例演示,帮助理解线程创建与状态管理。掌握这些基础,有利于后续学习线程同步、并发控制和高级多线程开发。考生应重点理解start()与run()的区别,线程状态转移,以及线程安全的预备知识。


关键知识点

  • 线程是程序执行的最小单位,实现多任务并发
  • Java中创建线程的两种方式:继承Thread类和实现Runnable接口
  • 线程生命周期包括新建、就绪、运行、阻塞、等待、计时等待、终止七种状态
  • 启动线程必须调用start()方法,不能直接调用run()
  • 线程优先级影响调度,但不保证绝对执行顺序
  • 多线程共享资源时需注意线程安全,避免数据冲突
  • 线程状态可通过getState()方法查看,便于调试
  • sleep()方法让线程进入计时等待状态
  • join()方法用于等待线程完成
  • 线程调度由操作系统和JVM共同完成

重点知识点

1

线程是程序执行的最小单位,实现多任务并发

2

Java中创建线程的两种方式:继承Thread类和实现Runnable接口

3

线程生命周期包括新建、就绪、运行、阻塞、等待、计时等待、终止七种状态

4

启动线程必须调用start()方法,不能直接调用run()

5

线程优先级影响调度,但不保证绝对执行顺序

6

多线程共享资源时需注意线程安全,避免数据冲突

7

线程状态可通过getState()方法查看,便于调试

8

sleep()方法让线程进入计时等待状态

9

join()方法用于等待线程完成

10

线程调度由操作系统和JVM共同完成