首页...线程的基本概念——多线程与并发编程入门
面向对象程序设计第五章 多线程与并发编程/第一节 线程的基本概念

线程的基本概念——多线程与并发编程入门

2026-03-24

第五章 多线程与并发编程

第一节 线程的基本概念

概述

随着计算机硬件性能的提升和多核处理器的普及,多线程编程成为现代软件开发中不可或缺的技术。多线程不仅可以提高程序的执行效率,还能提升资源利用率和用户体验。本节将系统介绍线程的基本概念,帮助考生理解线程的定义、特点、生命周期及其与进程的关系,为后续多线程编程技术奠定坚实基础。

学习目标:

  • 理解线程的定义及其作用
  • 掌握线程与进程的区别和联系
  • 熟悉线程的生命周期及状态转换
  • 了解线程的创建、启动和终止过程
  • 通过实例加深对线程基本概念的理解

核心概念

线程(Thread)

线程是操作系统能够进行运算调度的最小单位,是程序执行的基本顺序单元。一个进程可以包含多个线程,这些线程共享进程的资源,但有独立的执行路径。

进程(Process)

进程是系统进行资源分配和调度的基本单位。每个进程拥有独立的内存空间、系统资源和至少一个线程。

并发(Concurrency)

在单核处理器上,多个线程交替执行,看似同时运行,称为并发;多核处理器上,线程真正同时执行,称为并行。

线程状态

线程在其生命周期中会经历多个状态,常见的有新建、就绪、运行、阻塞和终止。

线程调度

操作系统负责将CPU时间片分配给不同线程,实现线程的切换和执行。


原理分析

线程与进程的关系

线程是运行在进程内部的执行单元,多个线程共享进程的内存空间、文件描述符等资源,但线程有自己的程序计数器、栈和寄存器集合。

特性 进程 线程
资源拥有 独立拥有内存空间和系统资源 共享进程的资源
调度单位 操作系统调度的基本单位 操作系统调度的基本单位
开销 创建销毁开销大 创建销毁开销小
通信方式 进程间通信(IPC)复杂 线程间通信简单(共享内存)

线程生命周期

线程生命周期由多个状态构成,状态转换受多种因素影响:

  • 新建(New):线程对象被创建,尚未开始执行。
  • 就绪(Runnable):线程准备好运行,等待CPU分配时间片。
  • 运行(Running):线程获得CPU,开始执行任务。
  • 阻塞(Blocked):线程因等待某些条件(如I/O、锁)而暂停执行。
  • 终止(Terminated):线程执行完毕或被强制结束。

线程状态转换由线程调度器和同步机制控制。

线程调度原理

线程调度是操作系统分配CPU时间给线程的过程,主要调度方式有:

  • 抢占式调度:操作系统强制中断当前线程,切换到其他线程。
  • 非抢占式调度:线程主动放弃CPU,调度器切换线程。

调度策略包括先来先服务(FCFS)、时间片轮转(Round Robin)、优先级调度等。


详细内容

1. 线程的定义和作用

线程,俗称“轻量级进程”,是程序执行的最小单位。多线程能够让程序在同一进程内同时执行多条指令流,极大提升程序的响应性和资源利用率。例如,网页浏览器可以同时处理页面渲染、用户交互和网络请求。

线程的主要作用包括:

  • 提高程序并发性,多任务并行处理
  • 优化资源利用,共享内存减少开销
  • 提升程序响应速度,避免界面卡顿

2. 线程与进程的区别

进程和线程的最大区别在于资源拥有和调度单位。进程拥有独立的资源空间,线程共享进程资源。创建进程的开销比线程大很多。

在多线程编程中,多个线程共享进程的地址空间,使得线程间通信更加高效,但也带来同步和安全问题。

3. 线程的生命周期详解

线程的生命周期是理解多线程控制的关键。线程从创建到结束经历五个状态:

  • 新建(New):线程对象创建,但尚未调用start()
  • 就绪(Runnable):调用start()后线程进入就绪队列,等待CPU时间
  • 运行(Running):CPU调度运行线程
  • 阻塞(Blocked):等待资源、I/O或同步锁
  • 终止(Terminated):线程执行结束或异常终止

线程状态转换示意:

  • 新建 -> 就绪(调用start)
  • 就绪 -> 运行(CPU调度)
  • 运行 -> 阻塞(等待I/O或锁)
  • 阻塞 -> 就绪(资源可用)
  • 运行 -> 终止(执行完毕)

4. 线程的创建与启动

多线程程序首先需要创建线程对象。常用方式有:

  • 继承Thread类:重写run()方法,通过start()启动线程
  • 实现Runnable接口:实现run()方法,传入Thread构造函数启动

调用start()方法会启动线程,系统调用底层线程调度机制。

5. 线程的终止方式

线程终止主要有两种:

  • 正常结束:run()方法执行完毕
  • 强制终止:调用interrupt()请求中断,线程捕获中断信号后结束

强制终止需谨慎,防止资源未释放和数据不一致。


实例分析

案例一:继承Thread类创建线程

背景:编写一个线程类打印数字1-5。

代码示例

class MyThread extends Thread {
    public void run() {
        for(int i=1; i<=5; i++) {
            System.out.println(getName() + ": " + i);
            try {
                Thread.sleep(500); // 模拟耗时任务
            } catch (InterruptedException e) {
                System.out.println(getName() + " 被中断");
            }
        }
    }
}

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

分析

  • 通过继承Thread类创建线程
  • 两个线程交替执行,体现并发效果
  • 使用sleep模拟阻塞状态

结论:线程启动后进入就绪,获取CPU时间片后运行,交替打印输出。


案例二:实现Runnable接口创建线程

背景:实现一个线程类打印字母A-E。

代码示例

class MyRunnable implements Runnable {
    public void run() {
        for(char c='A'; c<='E'; c++) {
            System.out.println(Thread.currentThread().getName() + ": " + c);
            try {
                Thread.sleep(400);
            } catch (InterruptedException e) {
                System.out.println("线程被中断");
            }
        }
    }
}

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

分析

  • 通过实现Runnable接口创建线程,增强了类的灵活性
  • 线程共享同一Runnable对象,体现资源共享

结论:Runnable方式更灵活,有利于多线程代码的解耦。


案例三:线程生命周期状态演示

背景:演示线程从新建到终止的状态变化。

代码示例

public class LifeCycleDemo {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            System.out.println("线程运行中...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("线程被中断");
            }
            System.out.println("线程结束");
        });

        System.out.println("状态:" + t.getState()); // NEW
        t.start();
        System.out.println("状态:" + t.getState()); // RUNNABLE

        Thread.sleep(500);
        System.out.println("状态:" + t.getState()); // TIMED_WAITING

        t.join();
        System.out.println("状态:" + t.getState()); // TERMINATED
    }
}

分析

  • 通过getState()方法查看线程状态
  • 观察新建、运行、阻塞(睡眠)、终止状态

结论:线程状态随着执行过程动态变化,理解有助于调试和设计多线程程序。


常见误区

  1. 线程直接调用run()方法代替start()

    • 错误做法会导致线程在当前线程中顺序执行,无法实现多线程并发。
    • 正确做法是调用start()启动线程,使线程进入就绪状态。
  2. 忽视线程安全与资源共享问题

    • 多线程共享资源时未加同步,导致数据竞争和不一致。
    • 应使用同步机制(如synchronized)保护共享资源。
  3. 滥用强制终止线程

    • 使用stop()等方法强制终止,会造成资源未释放。
    • 应使用中断机制或标志变量安全结束线程。
  4. 线程生命周期状态理解混淆

    • 将线程状态等同于线程是否执行,忽略阻塞和就绪状态。
    • 应准确理解状态间转换和线程调度的关系。
  5. 忽略线程调度不确定性

    • 误以为线程执行顺序固定,忽略调度器分配的随机性。
    • 应设计无序执行情况下也能正确工作的程序。

应用场景

  1. 图形界面程序

    • 主线程负责界面响应,子线程处理耗时操作,避免界面卡顿。
  2. 网络服务器

    • 通过多线程同时处理多个客户端请求,提高吞吐量。
  3. 实时数据处理

    • 多线程并发处理数据流,提升处理效率。
  4. 并行计算

    • 多核心CPU上划分任务线程,实现计算加速。
  5. 异步任务执行

    • 后台线程执行定时任务或消息监听,主线程继续业务逻辑。

知识拓展

  • 线程池技术:管理线程复用,减少创建销毁开销,提高效率。
  • 线程同步机制:锁(synchronized、ReentrantLock)、信号量(Semaphore)、条件变量(Condition)等。
  • 线程通信:wait()、notify()、notifyAll()实现线程间协作。
  • 线程安全设计:不可变对象、原子操作、线程安全集合。
  • 并发工具类:Java.util.concurrent包提供丰富并发工具。

总结回顾

本节内容系统介绍了线程的基本概念和原理,重点包括:

  • 线程定义和作用,线程是程序执行的最小单位
  • 线程与进程的区别,线程共享进程资源但拥有独立执行路径
  • 线程生命周期及状态转换,理解新建、就绪、运行、阻塞和终止状态
  • 线程的创建、启动和终止方法,掌握Thread类和Runnable接口的使用
  • 线程调度原理,理解抢占式和非抢占式调度策略
  • 通过实例演示线程创建和生命周期状态,强化理解
  • 常见误区警示,避免线程编程中的常见错误
  • 多线程应用场景介绍,联系实际提升学习兴趣

深入掌握本节内容,是理解多线程与并发编程的基础,有助于后续学习线程同步、线程安全和并发设计模式。


祝你学习进步,顺利通过全国计算机等级考试四级面向对象程序设计科目!

重点知识点

1

线程的定义及作用:执行程序的最小单位,实现并发

2

线程与进程的区别和联系:资源拥有与调度单位的差异

3

线程生命周期及状态转换:新建、就绪、运行、阻塞、终止

4

线程的创建与启动方式:继承Thread类和实现Runnable接口

5

线程调度原理:抢占式和非抢占式调度策略

6

线程的终止方式及注意事项

7

多线程编程常见误区及正确做法

8

多线程实际应用场景及意义

9

线程基本操作的典型实例解析

10

相关多线程技术的知识拓展方向