并发和并行的基础知识

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. 总结

  • 并发: 通过任务切换,多个任务在同一时间段内交替运行,强调任务管理和逻辑上的"同时进行"。
  • 并行: 依赖多核或分布式系统,多个任务在物理上真正同时运行,强调性能和效率提升。
相关推荐
学长毕设4 分钟前
基于SpringBoot的游乐园管理系统-附源码
java·spring boot·后端
SimonKing32 分钟前
震惊:怎么回事,opencode一轮对话耗尽免费额度
java·后端·程序员
装不满的克莱因瓶35 分钟前
【SpringAI Alibaba】ReactAgent响应SSE实时流式传输案例实战
java·人工智能·ai·sse·springai
杨凯凡39 分钟前
Spring Boot 文件上传怎么做才安全?流式落盘、路径校验与数据库一致性实战
java·spring boot·文件上传·后端安全·数据库一致性
这个昵称不容易1 小时前
旅游管理系统的设计与实现(SpringBoot + MySQL + Vue 前后端分离)
java·springboot·毕设
Rain的Java大神之路1 小时前
LeetCode 37 解数独面试攻略:回溯 + 位掩码 + MRV,从暴力到毫秒级求解
java·后端·leetcode
天天被压力2 小时前
【A股分钟级高频数据完全手册 #11】券商实时行情数据接口:实时交易(券商源)接入与字段
java·人工智能·python
天天被压力2 小时前
【A股分钟级高频数据完全手册 #12】股票五档盘口数据接口:买卖五档实时盘口解析
java·人工智能·python
Wang's Blog11 小时前
Java 项目实战: 交友项目 - FastDFS:入门案例
java·开发语言·交友
叼烟扛炮11 小时前
[LangChain] 学习笔记(06):突破大模型限制——结构化输出(Structured Output)
windows·笔记·学习·langchain