程序设计实践6w-线程、时间函数和设计问题

上传人:今*** 文档编号:107411282 上传时间:2019-10-19 格式:PPT 页数:51 大小:568.50KB
返回 下载 相关 举报
程序设计实践6w-线程、时间函数和设计问题_第1页
第1页 / 共51页
程序设计实践6w-线程、时间函数和设计问题_第2页
第2页 / 共51页
程序设计实践6w-线程、时间函数和设计问题_第3页
第3页 / 共51页
程序设计实践6w-线程、时间函数和设计问题_第4页
第4页 / 共51页
程序设计实践6w-线程、时间函数和设计问题_第5页
第5页 / 共51页
点击查看更多>>
资源描述

《程序设计实践6w-线程、时间函数和设计问题》由会员分享,可在线阅读,更多相关《程序设计实践6w-线程、时间函数和设计问题(51页珍藏版)》请在金锄头文库上搜索。

1、提纲,1. 使用线程实现任务并发 2. 模块化和工程 3. 概要设计要点 4. 时间控制函数 5. 有限状态自动机解题,1.使用线程实现任务并发,问题的引出:以电梯控制系统为例 目前能想到的程序主体结构 main() while (1) get_input(); /接收电梯服务请求 state_trans(); /计算此刻电梯的状态 print_message(); /输出电梯此刻的状态 time_count(); /时间片推进一个 思考:上述结构不合理之处?,3,1.使用线程实现任务并发,上述结构不合理之处:必须接收服务请求后才能输出电梯状态,与现实中的电梯运行不符! 程序结构的改进: 从上

2、述代码中删除get_input(),从而实现每隔一小段时间就刷新电梯当前状态 main() while (1) state_trans(); /计算此刻电梯的状态 print_message(); /输出电梯此刻的状态 time_count(); /时间片推进一个 ,4,1.使用线程实现任务并发,但是,程序必须要能接收电梯服务请求,如何处理服务请求的输入? 理想状态: 电梯服务请求的接收和电梯状态的计算输出能同时进行,互不影响 但是,能否实现? 答案是:使用线程,电梯状 态计算 和输出,共享内存区,接收服,务请求,5,1.使用线程实现任务并发,进程 一个独立程序的每一次运行称为一个进程,例如

3、用字处理软件编辑文稿时,同时打开mp3播放程序听音乐,这两个独立的程序在同时运行,称为两个进程 进程是计算机资源分配的基本单位。设置一个进程要占用相当一部分处理器时间和内存资源 大多数操作系统不允许进程访问其他进程的内存空间,进程间的通信很不方便,编程模型比较复杂,1.使用线程实现任务并发,线程 一个程序中多段代码同时并发执行,称为多线程 通过多线程,一个进程表面上看同时可以执行一个以上的任务并发 线程是被系统独立调度和分派的基本单位。进程用来分配资源,实际运行的是线程,每个进程至少包含一个线程。同一进程中的多个线程之间可以并发执行 线程自己不拥有系统资源,但它可与同属一个进程的其它线程共享进

4、程所拥有的全部资源,1.使用线程实现任务并发,在C程序中要创建线程,可以调用Windows操作系统提供的创建线程的函数CreateThread : HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, DWORD dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, DWORD lpThreadId);,LPVOID是一个Void类型的指针,也就是说你可以将任意类型的指针赋值给LPVOID

5、类型的变量。 DWORD是32位无符号整数。,1.使用线程实现任务并发,lpThreadAttributes表示创建线程的安全属性,NT下有用。可赋值为NULL。 dwStackSize指定线程栈的尺寸,如果为0则与进程主线程栈相同。 lpStartAddress指定线程开始运行的地址。赋值为指向函数的指针,即函数名。 lpParameter表示传递给线程的32位的参数。 若无参数则赋值为NULL。 dwCreationFlags表示是否创建后挂起线程(取值CREATE_SUSPEND),挂起后调用ResumeThread继续执行。若不挂起则赋值为0。 lpThreadId用来存放返回的线程I

6、D。 DWORD ThreadID1 = 1; HANDLE hRead1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput, NULL,0,1.使用线程实现任务并发,1.使用线程实现任务并发 main函数中创建两个线程,线程1从键盘接收字符数据写入变量ch中,线程2读取ch写入文件中。,1.使用线程实现任务并发,#include #include /使用线程编程时,下面这两个头文件必须包含 #include #include void getInput(void); /线程1要运行的函数 void output(void); /线程

7、2要运行的函数 char ch=A; /全局变量,1.使用线程实现任务并发,int main() int i; /*创建线程1:从键盘接收字符写入到全局变量ch中 */ DWORD ThreadID1 = 1; HANDLE hRead1 = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput,NULL,0,1.使用线程实现任务并发,while(1) /*死循环。本循环必须要有,否则main函数一结束,另两个线程也就结束了。*/ system(“PAUSE“); return 0; ,1.使用线程实现任务并发,void getInput(v

8、oid) int i; while(1) printf(“input a charn“); ch=getchar(); fflush(stdin);/使回车不被读取 ,1.使用线程实现任务并发,void output(void) long int i; FILE * cfPtr=NULL; if( (cfPtr=fopen(“data.txt“,“w“)=NULL) printf(“cant open filen“); else while(1) for(i=1;i=2222222;i+); /延迟 fputc(ch,cfPtr); /字符写入文件 fflush(cfPtr); /确保不关闭文

9、件情况下数据能写入 ,信号量,例子问题 字符被重复写入多次 如何解决 线程间采用信号量进行同步控制,线程在电梯控制系统中的使用,考虑现实中安装在电梯上的软件:接收电梯服务请求和计算电梯状态、从而控制电梯的运行是并行的 因此我们可以考虑在模拟电梯控制系统中设计一个线程专门用于接收电梯服务请求,另一个线程实行电梯的状态计算和状态输出,电梯状 态计算 和输出,线程共享内存区,接收服,务请求,电梯状态计算和输出:从共享内存区读取电梯请求,计算下一目标楼层,从而确定电梯的下一状态。,接收服务请求:接收电梯请求,将请求保存到内存。,/主线程 main() DWORD ThreadID = 1; /创建线程

10、(对应于函数input(),用于接收电梯输入; HANDLE hRead = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput,NULL,0, /进行变量初始化工作,线程在电梯控制系统中的使用,while (1) state_trans(); ();/根据自动机模型决定此刻电梯的状态 print_message();/*输出电梯此刻的状态*/ control(); /*根据控制策略确定下一目标楼层,这在 state_trans()中要用到 */ time_count(); /*时间片推进一个*/ ,线程在电梯控制系统中的使用,/接收输入线

11、程 void getInput(void) char ch; while(1) ch=getchar(); /加入代码:将ch翻译成相应请求并保存; time_count();/时间片推进一个; ,线程在电梯控制系统中的使用,提纲,1. 使用线程实现任务并发 2. 模块化和工程 3. 概要设计要点 4. 时间控制函数 5. 有限状态自动机解题,2.模块化和工程,模块的定义 一般把用一个名字就可调用的一段程序称为“模块”,如子程序、函数等。 模块的基本属性: 功能:描述该模块实现什么功能 逻辑:描述模块内部怎么做 状态:该模块使用时的环境和条件 除了基本属性,还需描述模块的内部和外部特性 模块的

12、外部特性:模块的模块名、参数表 模块的内部特性:完成其功能的程序代码和仅供该模块内部使用的数据 通常是先确定模块的外部特性,再确定其内部特性。,2.模块化和工程,函数是最小的模块,若干个紧密相关的函数可以组成更大的模块源文件。 一条好的原则就是保持模块的紧凑性即在同一个源文件中只包含那些在逻辑上与其相关的函数。,2.模块化和工程,模块化:把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,所有模块集成起来构成的整体可完成用户的所有需求。 模块化意义 降低了系统的复杂性,使系统容易修改和重用; 推动系统各部分的并行开发,提高开发效率。 使用工程来组织多个源文件。 将功能紧密相关的若干

13、个函数组成单独的源文件。,复杂问题 较小问题 高层模块 从整体上把握问题,隐蔽细节,分解,提纲,1. 使用线程实现任务并发 2. 模块化和工程 3. 概要设计要点 4. 时间控制函数 5. 有限状态自动机解题,3.概要设计要点,概要设计的目的: 全局把握程序结构:进行程序的模块划分,设计模块之间如何相互调用来完成程序要求的功能。 定义关键变量,用来存储各模块共享的数据;定义常量。 设计关键的算法,主要是控制策略,提前对关键的、较难解决的问题进行处理。,3.概要设计要点,概要设计主要从以下5个方面考虑: 用户界面:界面友好,要能从界面提示信息了解电梯/火车/银行的状态和请求。 自动机模型:有自动

14、机状态迁移图,状态迁移图上描述了引起状态迁移的条件,并且要在文档中附加说明进入某状态要做的动作。 全局变量:较全面地给出了各个函数要共享的数据。 程序模块化:函数接口说明,函数调用关系说明。 调度算法:给出电梯、小火车调度或者银行调度的算法。,3-1 用户界面(1),点评:界面上增加各层向上向下请求对应的字符,以便于操作;电梯请求展示区需要再细化,分别显示:向上请求、向下请求,电梯内请求。,3-1 用户界面(2),电梯内部描述,3-2 自动机模型,思考:该图有什么待改进之处?,3-3 全局变量,函数之间如何通信?全局变量或者参数 线程之间如何通信?全局变量或者参数 全局变量设计考虑要全面; 应

15、明确给出定义,如: int destLayer;/记录电梯下一目标服务楼层,3-4 程序模块化,应该说明程序的模块结构,包括: 整个程序分成哪几个文件? 每一个文件里面包含哪些函数?函数原型说明? 图示说明函数调用关系。 要进行清楚的描述。,3-5 关键算法,给出调度算法设计 算法思路要有助于进一步设计,不能很粗略,提纲,1. 使用线程实现任务并发 2. 模块化和工程 3. 概要设计要点 4. 时间控制函数 5. 有限状态自动机解题,4.1-计时函数,while (1) state_trans(); ();/根据自动机模型决定此刻电梯的状态 print_message();/*输出电梯此刻的状

16、态*/ control(); /*根据控制策略确定下一目标楼层,这在 state_trans()中要用到 */ time_count(); /*时间片推进一个*/ ,4.1-计时函数,clock_t clock( void ); ANSI标准库中的time.h头文件,其中定义了日期和时间的处理函数。 这个函数返回从“启动程序”到“程序中调用clock()函数”之间的CPU时钟计时单元(clock tick)数,在MSDN中称之为挂钟时间(wal-clock)。其中clock_t是用来保存时间的数据类型,长整型。 clock tick:CPU时钟计时单元,时间长短由CPU控制。一个clock tick不是CPU的一个时钟周期,而是C/C+

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 高等教育 > 大学课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号