C#小案例-->让两个线程交替打印偶数和奇数值(并发)

作者:MM_MS日期:2025/11/28

方法一:

编写代码实现切换逻辑
1using System;
2using System.Threading;
3
4namespace 让两个线程交替打印偶数和奇数值_并发_
5{
6    internal class Program
7    {
8        // ===================== 共享资源与同步工具 =====================
9        // 1. 偶数线程的当前值(初始为0,每次+2,打印偶数)
10        private static int _evenNum = 0;
11        // 2. 奇数线程的当前值(初始为99,每次-2,打印奇数)
12        private static int _oddNum = 99;
13        // 3. 同步事件:控制偶数线程的执行权限
14        // 初始为“有信号”(true)→ 让偶数线程先执行(对应案例中先打印0)
15        private static AutoResetEvent _evenEvent = new AutoResetEvent(initialState: true);
16        // 4. 同步事件:控制奇数线程的执行权限
17        // 初始为“无信号”(false)→ 奇数线程等待偶数线程完成后再执行
18        private static AutoResetEvent _oddEvent = new AutoResetEvent(initialState: false);
19
20        static void Main(string[] args)
21        {
22            Console.WriteLine("线程交替打印开始:");
23            Console.WriteLine("-------------------------------------\n");
24
25            // ===================== 偶数线程(打印偶数) =====================
26            // 创建线程:负责打印偶数(0、2、4...)
27            Thread evenThread = new Thread(PrintEvenNumbers)
28            {
29                Name = "偶数线程(程A)" // 设置线程名称,便于调试/标识
30            };
31
32            // ===================== 奇数线程(打印奇数) =====================
33            // 创建线程:负责打印奇数(99、97、95...)
34            Thread oddThread = new Thread(PrintOddNumbers)
35            {
36                Name = "奇数线程(程B)" // 设置线程名称
37            };
38
39            // 启动两个线程(此时线程进入就绪状态,等待CPU调度)
40            evenThread.Start();
41            oddThread.Start();
42
43            // 主线程等待子线程执行完毕(避免主线程提前退出)
44            evenThread.Join();
45            oddThread.Join();
46
47            Console.WriteLine("\n-------------------------------------");
48            Console.WriteLine("所有数字打印完成,程序结束");
49        }
50
51
52        /// <summary>
53        /// 偶数线程的执行逻辑:打印偶数,完成后通知奇数线程
54        /// </summary>
55        private static void PrintEvenNumbers()
56        {
57            // 循环条件:偶数不超过99(与奇数范围保持一致)
58            while (_evenNum <= 99)
59            {
60                // 等待“偶数线程的执行信号”:
61                // - 初始为“有信号”,线程直接执行;
62                // - 执行后信号会自动重置为“无信号”,需等待奇数线程通知才能再次执行
63                _evenEvent.WaitOne();
64
65                // 打印当前偶数(格式与案例一致:线程名 + 数值)
66                Console.WriteLine($"{Thread.CurrentThread.Name}: {_evenNum}");
67
68                // 偶数线程的数值自增2(获取下一个偶数)
69                _evenNum += 2;
70
71                // 通知奇数线程:可以执行打印操作了
72                // 将“奇数线程的执行信号”设为“有信号”,唤醒等待中的奇数线程
73                _oddEvent.Set();
74                Thread.Sleep(500);
75            }
76        }
77
78        /// <summary>
79        /// 奇数线程的执行逻辑:打印奇数,完成后通知偶数线程
80        /// </summary>
81        private static void PrintOddNumbers()
82        {
83            // 循环条件:奇数不小于0(与偶数范围保持一致)
84            while (_oddNum >= 0)
85            {
86                // 等待“奇数线程的执行信号”:
87                // - 初始为“无信号”,线程会阻塞;
88                // - 需等待偶数线程执行完毕后,通过_oddEvent.Set()唤醒
89                _oddEvent.WaitOne();
90
91                // 打印当前奇数(格式与案例一致:线程名 + 数值)
92                Console.WriteLine($"{Thread.CurrentThread.Name}: {_oddNum}");
93
94                // 奇数线程的数值自减2(获取下一个奇数)
95                _oddNum -= 2;
96
97                // 通知偶数线程:可以执行打印操作了
98                // 将“偶数线程的执行信号”设为“有信号”,唤醒等待中的偶数线程
99                _evenEvent.Set();
100                Thread.Sleep(500);
101            }
102        }
103    }
104}
105
测试演示

方法二:

创建 Winform 项目并设计界面

编写代码实现切换逻辑
1using System;
2using System.Threading;
3using System.Windows.Forms;
4
5namespace _01_奇偶数交替打印
6{
7    public partial class Form1 : Form
8    {
9        public Form1()
10        {
11            InitializeComponent();
12        }
13
14        private void Form1_Load(object sender, EventArgs e)
15        {
16            // 窗体加载时,关闭跨线程非法调用检查机制
17            Control.CheckForIllegalCrossThreadCalls = false;
18        }
19
20        private void button1_Click(object sender, EventArgs e)
21        {
22            // 创建两个线程
23            Thread threadA = new Thread(PrintOdd);// 打印奇数
24            threadA.Name = "线程A";
25            threadA.Start(99);
26            Thread threadB = new Thread(PrintEven);// 打印偶数
27            threadB.Name = "线程B";
28            threadB.Start(100);
29        }
30
31        private void PrintOdd(object num)// 给线程当中的参数传递值,线程所绑定的方法参数类型只能是object类型
32        {
33            for (int i = (int)num; i >= 1; i-=2)
34            {
35                textBox1.AppendText(Thread.CurrentThread.Name +"--->"+ i.ToString() + "\r\n");
36                Thread.Sleep(500);
37            }
38        }
39
40        private void PrintEven(object num)
41        {
42            for (int i = 0; i <= (int)num; i+=2)
43            {
44                textBox1.AppendText(Thread.CurrentThread.Name + "--->" + i.ToString() + "\r\n");
45                Thread.Sleep(500);
46            }
47        }
48    }
49}
50
测试演示

希望对大家有所帮助。感谢大家的关注和点赞。


C#小案例-->让两个线程交替打印偶数和奇数值(并发)》 是转载文章,点击查看原文


相关推荐


手写 EventEmitter:深入理解发布订阅模式
1024肥宅2025/12/7

引言 在 JavaScript 开发中,事件驱动编程是构建可维护、可扩展应用的核心范式之一。从浏览器 DOM 事件到 Node.js 的异步 I/O,从 Vue 的组件通信到 React 的状态管理,发布订阅模式无处不在。 通过手写一个符合 Node.js EventEmitter 标准的实现,我们不仅能深入理解事件驱动架构的设计原理,还能掌握 JavaScript 中闭包、内存管理、设计模式等核心概念。更重要的是,这是面试中常见的高级题目,能体现你对JavaScript设计模式的理解深度。 本


基于 Gradio 构建神经网络 GUI 实验平台:感知器 / BP/Hopfield/AlexNet/VGG/ResNet 一站式实现
晞微2025/12/15

引言 神经网络实验往往需要编写大量代码、调试参数、手动可视化结果,对于初学者而言门槛较高。传统的命令行式实验方式不仅操作繁琐,还难以直观展示算法效果。本文基于Gradio框架,构建了一个集经典神经网络(感知器、BP、Hopfield) 和深度学习模型(AlexNet/VGG/ResNet) 于一体的可视化 GUI 实验平台,无需编写代码,仅通过界面交互即可完成各类神经网络实验,大幅降低了实验门槛。 本平台支持以下核心实验: 感知器二分类实验BP 神经网络非线性函数拟合实验Hopfield


OSPF协议
Suchadar2025/12/23

一、OSPF 协议概述         OSPF(Open Shortest Path First,开放式最短路径优先协议)是一种链路状态路由协议,隶属于内部网关协议(IGP,Interior Gateway Protocol)范畴,核心功能是实现自治系统(AS,Autonomous System)内部路由器之间的路由信息交换,为数据传输提供最优路径指引。         分层网络架构:通过 “区域(Area)” 和 “特殊角色路由器” 划分网络层级,有效解决单区域网络中路由信息泛滥、设备资


程序员副业 | 2025年12月复盘
嘟嘟MD2026/1/2

本文首发于公众号:嘟爷创业日记 。 我已经坚持日更600天+,欢迎过来追剧~ 大家好,我是嘟嘟MD,一个10年程序员,现在离职创业,有700天了,我每个月都会写一篇总结复盘,让大家可以近距离看看一个离职程序员都在干什么,今天这篇是十二月份的总结,大概2000字,略长,有空的可以翻翻,希望对大家有一丢丢的借鉴作用! 一、月度大事 今天先把12月的复盘写了, 改天再把25年的复盘整理哈,这一年还是经历了很多事情,需要好好总结复盘 1:公众号运营+B站视频运营 公众号和B站视频运营目前还是最高


Java是当今最优雅的开发语言
richxu202510012026/1/10

我认为Java是当今最优雅的开发语言! 天然成熟的生态 !! 项目内部代码都各种积木化(模块化) (离不开spring boot的加持) 我也曾用过Delphi ,C#,Python 开发 ! 随感而发,不喜勿喷        #嵌入式 #电子信息 #编程 #软件设计与开发 #找工作 #后端开发 #单片机 #小红书#Java


【Python爬虫实战】用 Flet 把爬虫做成手机 App
MoonPointer-Byte2026/1/18

有没有想过,把你写的爬虫装进手机里? 比如: 想听歌时,后台自动爬取音乐的资源并播放; 想搜图时,后台自动爬取 高清图接口并下载; 想看人时,一键聚合搜索社交用户数据。 今天我们将实战一个MoonMusic。它的核心不是 UI,而是强大的异步数据采集层。 🔧 核心技术栈 数据采集 (Crawler): httpx (异步 HTTP 请求), BeautifulSoup4 (HTML 解析) 并发控制 (Concurrency): asyncio (协程调度) 数据可视


🔥别再用递归了!WeakMap 的影子索引“让树不再是树!”
vilan_微澜2026/1/28

一、前言 大家好,我是微澜。今天来分享一个基于 WeakMap 实现的快速对树形结构数据进行增删改查操作的useTree hook函数,它是基于JavaScript 的 WeakMap 特性,在不改动原始数据的前提下,实现了一套 O(1) 查找的影子索引结构,这个影子其实就是对象的引用地址,让树形数据操作像操作数组一样简单! 二、为什么选择 WeakMap? 1. 非侵入性 (Non-invasive) 通过 WeakMap 在内存中构建了一套 Node -> Parent 的映射。原始数据对象


基于uview-pro的u-dropdown扩展自己的dropdown组件
LC同学479812026/2/6

基于uview-pro的u-dropdown扩展自己的dropdown组件 uview-pro的u-dropdown只能是菜单,且只能向下展开,当前组件采用它的核心逻辑,去除多余逻辑,兼容上/下展开,以及自定义展示的内容,不再局限于菜单形式 import type { ExtractPropTypes, PropType } from 'vue'; import { baseProps } from 'uview-pro/components/common/props'; /** * u-


Flutter三方库适配OpenHarmony【apple_product_name】异步调用与错误处理
淼学派对2026/2/14

前言 欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net 本文将围绕 apple_product_name 的实际 API,从 Future 基础到全局错误兜底,给出一套完整的异步调用与错误处理方案。 先给出结论式摘要: 所有 API 返回 Future:getMachineId()、getProductName()、lookup() 都是异步的,必须 await 或 .then()三类异常要分层捕获:PlatformExc


AI 系统架构
lizhongxuan2026/2/23

AI 系统看起来很复杂,但核心可以压缩成三句话: 尽量少搬数据:很多时候不是算不动,而是数据搬运太慢。 尽量提高有效计算密度:让硬件更多时间在做有价值的乘加计算。 尽量重叠计算与通信:训练和推理都要避免“设备空等”。 换句话说,AI 性能问题本质上是 计算(Compute)+ 访存(Memory)+ 通信(Communication) 的协同问题。 1. AI 系统栈 层级主要职责典型问

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2026 XYZ博客