并发和并行的基础知识

1. 并发(Concurrency)的例子

场景:单核计算机同时运行多个应用程序

假设你正在使用一台单核 CPU 的计算机,你同时打开了以下任务:

  • 任务 A:听音乐(音乐播放器)。
  • 任务 B:编写文档(Word 文档)。
  • 任务 C:下载文件(浏览器)。

虽然只有一个 CPU 核心,这些任务似乎在"同时"进行,但实际上计算机通过快速切换任务来实现并发:

如何实现并发?

  1. 任务切片

    • CPU 分配时间片(如 10 毫秒)给每个任务。
    • 时间片到期后,切换到另一个任务。
  2. 任务调度

    • 操作系统(如 Windows 或 Linux)通过调度器管理任务的执行顺序。
    • 任务的切换对用户透明,用户感知不到切换过程。

具体流程:

  • 时间片 1:CPU 执行任务 A(播放音乐)。
  • 时间片 2:CPU 切换到任务 B(处理文档)。
  • 时间片 3:CPU 切换到任务 C(下载文件)。
  • 重复上述步骤。

尽管 CPU 在某一时刻只能执行一个任务,但因为切换速度极快(毫秒级),你会感觉这些任务在同时运行。


代码模拟:单线程并发任务

以下示例模拟单核 CPU 的任务切换:

java 复制代码
public class ConcurrencyExample {
    public static void main(String[] args) {
        Runnable musicTask = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Playing music...");
                sleep(100);
            }
        };

        Runnable documentTask = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Editing document...");
                sleep(100);
            }
        };

        Runnable downloadTask = () -> {
            for (int i = 0; i < 5; i++) {
                System.out.println("Downloading file...");
                sleep(100);
            }
        };

        // 按顺序执行任务,模拟任务切换
        for (int i = 0; i < 5; i++) {
            musicTask.run();
            documentTask.run();
            downloadTask.run();
        }
    }

    private static void sleep(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果

Playing music...
Editing document...
Downloading file...
Playing music...
Editing document...
Downloading file...
...
  • 每个任务交替运行,给人感觉是"同时"执行的。
  • 本质上是通过快速切换来模拟并发。

2. 并行(Parallelism)的例子

场景:多核计算机同时运行多个任务

现在假设你使用一台四核 CPU的计算机,仍然执行以下任务:

  • 任务 A:听音乐(音乐播放器)。
  • 任务 B:编写文档(Word 文档)。
  • 任务 C:下载文件(浏览器)。
  • 任务 D:视频压缩(FFmpeg)。

在多核环境下,不同任务可以真正同时运行,每个任务分配到一个 CPU 核心:

如何实现并行?

  1. 多核 CPU 的任务分配

    • CPU 核心 1:执行任务 A(音乐播放器)。
    • CPU 核心 2:执行任务 B(文档编辑)。
    • CPU 核心 3:执行任务 C(文件下载)。
    • CPU 核心 4:执行任务 D(视频压缩)。
  2. 真正的同时运行

    • 多核系统中,每个核心可以独立处理任务。
    • 这些任务在物理上同时运行,不需要时间片轮转。

代码模拟:多线程并行任务

以下代码使用多线程模拟多核 CPU 的并行执行:

java 复制代码
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ParallelismExample {
    public static void main(String[] args) {
        // 创建一个线程池,模拟 4 核 CPU
        ExecutorService executor = Executors.newFixedThreadPool(4);

        // 定义四个任务
        executor.submit(() -> playMusic());
        executor.submit(() -> editDocument());
        executor.submit(() -> downloadFile());
        executor.submit(() -> compressVideo());

        executor.shutdown();
    }

    private static void playMusic() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Playing music...");
            sleep(100);
        }
    }

    private static void editDocument() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Editing document...");
            sleep(100);
        }
    }

    private static void downloadFile() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Downloading file...");
            sleep(100);
        }
    }

    private static void compressVideo() {
        for (int i = 0; i < 5; i++) {
            System.out.println("Compressing video...");
            sleep(100);
        }
    }

    private static void sleep(int ms) {
        try {
            Thread.sleep(ms);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

运行结果(顺序可能不同):

Playing music...
Editing document...
Downloading file...
Compressing video...
Playing music...
Editing document...
Downloading file...
Compressing video...
...
  • 每个任务分配到不同的线程,线程在多核 CPU 上真正同时运行。
  • 输出顺序可能不同,取决于操作系统和线程调度器的工作方式。

3. 并发与并行的结合

场景:并发和并行的混合使用

假设:

  • 你有 4 核 CPU。
  • 运行 8 个任务(任务 A 到 H)。

操作系统会结合并发并行来调度任务:

  1. 并行
    • 4 个任务同时运行在 4 核 CPU 上。
  2. 并发
    • 当某个任务阻塞时(如 I/O 操作),CPU 切换到其他任务继续执行。
示意图
时间线: 核心 1   | A |   | B |   | A |   | B |
          核心 2   | C |   | D |   | C |   | D |
          核心 3   | E |   | F |   | E |   | F |
          核心 4   | G |   | H |   | G |   | H |

4. 实际应用场景

场景 并发(Concurrency) 并行(Parallelism)
浏览器加载网页 同时处理多个请求(图片、视频、CSS 文件) 在多核 CPU 上并行渲染页面、解码视频和执行脚本。
视频播放 同时缓冲、解码和播放视频流(逻辑上的并发)。 使用 GPU 解码并渲染视频帧(物理上的并行)。
编译代码 同时编译多个模块(逻辑并发)。 使用多核 CPU 同时编译多个模块(物理并行)。
AI 训练 同时加载数据、更新参数(逻辑并发)。 使用 GPU 同时训练多个神经网络或并行处理不同的数据批次。
操作系统任务调度 多个任务共享 CPU 时间片,逻辑上的并发。 多核 CPU 上任务真正同时运行。

5. 总结

  • 并发: 通过任务切换,多个任务在同一时间段内交替运行,强调任务管理和逻辑上的"同时进行"。
  • 并行: 依赖多核或分布式系统,多个任务在物理上真正同时运行,强调性能和效率提升。
相关推荐
广而不精zhu小白24 分钟前
CentOS Stream 9 挂载Windows共享FTP文件夹
linux·windows·centos
一休哥助手30 分钟前
全面解析 Linux 系统监控与性能优化
linux·运维·性能优化
二进制杯莫停32 分钟前
掌控网络流量的利器:tcconfig
linux
忒可君34 分钟前
C# winform 报错:类型“System.Int32”的对象无法转换为类型“System.Int16”。
java·开发语言
watl01 小时前
【Android】unzip aar删除冲突classes再zip
android·linux·运维
斌斌_____1 小时前
Spring Boot 配置文件的加载顺序
java·spring boot·后端
路在脚下@1 小时前
Spring如何处理循环依赖
java·后端·spring
一个不秃头的 程序员1 小时前
代码加入SFTP JAVA ---(小白篇3)
java·python·github
赵大仁1 小时前
在 CentOS 7 上安装 Node.js 20 并升级 GCC、make 和 glibc
linux·运维·服务器·ide·ubuntu·centos·计算机基础
vvw&1 小时前
Docker Build 命令详解:在 Ubuntu 上构建 Docker 镜像教程
linux·运维·服务器·ubuntu·docker·容器·开源