版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
线程、设计问题提纲1.使用线程实现任务并发2.模块化和工程3.概要设计要点4.时间控制函数5.有限状态自动机解题1.使用线程实现任务并发问题的引出:以电梯控制系统为例目前能想到的程序主体结构main(){while(1){get_input();//接收电梯服务请求state_trans();//计算此刻电梯的状态print_message();//输出电梯此刻的状态time_count();//时间片推进一个}}思考:上述结构不合理之处?
31.使用线程实现任务并发上述结构不合理之处:必须接收服务请求后才能输出电梯状态,与现实中的电梯运行不符!程序结构的改进: 从上述代码中删除get_input(),从而实现每隔一小段时间就刷新电梯当前状态main(){while(1){state_trans();//计算此刻电梯的状态print_message();//输出电梯此刻的状态time_count();//时间片推进一个}}41.使用线程实现任务并发但是,程序必须要能接收电梯服务请求,如何处理服务请求的输入?理想状态:电梯服务请求的接收和电梯状态的计算输出能同时进行,互不影响但是,能否实现?答案是:使用线程电梯状态计算和输出共享内存区接收服务请求51.使用线程实现任务并发进程一个独立程序的每一次运行称为一个进程,例如用字处理软件编辑文稿时,同时打开mp3播放程序听音乐,这两个独立的程序在同时运行,称为两个进程进程是计算机资源分配的基本单位。设置一个进程要占用相当一部分处理器时间和内存资源大多数操作系统不允许进程访问其他进程的内存空间,进程间的通信很不方便,编程模型比较复杂1.使用线程实现任务并发线程一个程序中多段代码同时并发执行,称为多线程通过多线程,一个进程表面上看同时可以执行一个以上的任务——并发线程是被系统独立调度和分派的基本单位。进程用来分配资源,实际运行的是线程,每个进程至少包含一个线程。同一进程中的多个线程之间可以并发执行线程自己不拥有系统资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源1.使用线程实现任务并发在C程序中要创建线程,可以调用Windows操作系统提供的创建线程的函数CreateThread:HANDLE
CreateThread(
LPSECURITY_ATTRIBUTES
lpThreadAttributes,
DWORD
dwStackSize,
LPTHREAD_START_ROUTINE
lpStartAddress,
LPVOID
lpParameter,
DWORD
dwCreationFlags,
DWORD
lpThreadId);
LPVOID是一个Void类型的指针,也就是说你可以将任意类型的指针赋值给LPVOID类型的变量。DWORD是32位无符号整数。1.使用线程实现任务并发lpThreadAttributes表示创建线程的安全属性,NT下有用。可赋值为NULL。dwStackSize指定线程栈的尺寸,如果为0则与进程主线程栈相同。lpStartAddress指定线程开始运行的地址。赋值为指向函数的指针,即函数名。lpParameter表示传递给线程的32位的参数。若无参数则赋值为NULL。dwCreationFlags表示是否创建后挂起线程(取值CREATE_SUSPEND),挂起后调用ResumeThread继续执行。若不挂起则赋值为0。lpThreadId用来存放返回的线程ID。DWORDThreadID1=1;HANDLEhRead1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput, NULL,0,&ThreadID1);1.使用线程实现任务并发1.使用线程实现任务并发 main函数中创建两个线程,线程1从键盘接收字符数据写入变量ch中,线程2读取ch写入文件中。1.使用线程实现任务并发#include<stdio.h>#include<stdlib.h>//使用线程编程时,下面这两个头文件必须包含#include<winsock.h>#include<winbase.h>voidgetInput(void);//线程1要运行的函数voidoutput(void);//线程2要运行的函数charch=‘A’;//全局变量1.使用线程实现任务并发intmain(){inti;
/*创建线程1:从键盘接收字符写入到全局变量ch中*/DWORDThreadID1=1;HANDLEhRead1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput,NULL,0,&ThreadID1);
/*创建线程2:用于将全局变量ch写入文件*/DWORDThreadID2=2;HANDLEhRead2=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)output,NULL,0,&ThreadID2);
1.使用线程实现任务并发while(1){/*死循环。本循环必须要有,否则main函数一结束,另两个线程也就结束了。*/}system("PAUSE"); return0;}1.使用线程实现任务并发voidgetInput(void){inti;
while(1){printf("inputachar\n");ch=getchar();fflush(stdin);//使回车不被读取}}1.使用线程实现任务并发voidoutput(void){longinti;FILE*cfPtr=NULL;if((cfPtr=fopen("data.txt","w"))==NULL)printf("can'topenfile\n");elsewhile(1){for(i=1;i<=2222222;i++);//延迟fputc(ch,cfPtr);//字符写入文件fflush(cfPtr);//确保不关闭文件情况下数据能写入}}信号量例子问题字符被重复写入多次如何解决线程间采用信号量进行同步控制线程在电梯控制系统中的使用考虑现实中安装在电梯上的软件:接收电梯服务请求和计算电梯状态、从而控制电梯的运行是并行的因此我们可以考虑在模拟电梯控制系统中设计一个线程专门用于接收电梯服务请求,另一个线程实行电梯的状态计算和状态输出电梯状态计算和输出线程共享内存区接收服务请求电梯状态计算和输出:从共享内存区读取电梯请求,计算下一目标楼层,从而确定电梯的下一状态。接收服务请求:接收电梯请求,将请求保存到内存。//主线程main(){DWORDThreadID=1;//创建线程(对应于函数input()),用于接收电梯输入;HANDLEhRead=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput,NULL,0,&ThreadID);
//进行变量初始化工作
线程在电梯控制系统中的使用while(1){state_trans();();//根据自动机模型决定此刻电梯的状态print_message();/*输出电梯此刻的状态*/
control();/*根据控制策略确定下一目标楼层,这在 state_trans()中要用到*/time_count();/*时间片推进一个*/}}线程在电梯控制系统中的使用//接收输入线程voidgetInput(void){charch;while(1){ ch=getchar();//加入代码:将ch翻译成相应请求并保存;time_count();//时间片推进一个;}}线程在电梯控制系统中的使用提纲1.使用线程实现任务并发2.模块化和工程3.概要设计要点4.时间控制函数5.有限状态自动机解题2.模块化和工程模块的定义一般把用一个名字就可调用的一段程序称为“模块”,如子程序、函数等。模块的基本属性:功能:描述该模块实现什么功能逻辑:描述模块内部怎么做状态:该模块使用时的环境和条件除了基本属性,还需描述模块的内部和外部特性模块的外部特性:模块的模块名、参数表模块的内部特性:完成其功能的程序代码和仅供该模块内部使用的数据通常是先确定模块的外部特性,再确定其内部特性。2.模块化和工程函数是最小的模块,若干个紧密相关的函数可以组成更大的模块--源文件。一条好的原则就是保持模块的紧凑性.即在同一个源文件中只包含那些在逻辑上与其相关的函数。2.模块化和工程模块化:把程序划分成独立命名且可独立访问的模块,每个模块完成一个子功能,所有模块集成起来构成的整体可完成用户的所有需求。模块化意义降低了系统的复杂性,使系统容易修改和重用;推动系统各部分的并行开发,提高开发效率。使用工程来组织多个源文件。将功能紧密相关的若干个函数组成单独的源文件。复杂问题较小问题高层模块从整体上把握问题,隐蔽细节分解提纲1.使用线程实现任务并发2.模块化和工程3.概要设计要点4.时间控制函数5.有限状态自动机解题3.概要设计要点概要设计的目的:全局把握程序结构:进行程序的模块划分,设计模块之间如何相互调用来完成程序要求的功能。定义关键变量,用来存储各模块共享的数据;定义常量。设计关键的算法,主要是控制策略,提前对关键的、较难解决的问题进行处理。3.概要设计要点概要设计主要从以下5个方面考虑:用户界面:界面友好,要能从界面提示信息了解电梯/火车/银行的状态和请求。自动机模型:有自动机状态迁移图,状态迁移图上描述了引起状态迁移的条件,并且要在文档中附加说明进入某状态要做的动作。全局变量:较全面地给出了各个函数要共享的数据。程序模块化:函数接口说明,函数调用关系说明。调度算法:给出电梯、小火车调度或者银行调度的算法。3-1用户界面(1)点评:界面上增加各层向上向下请求对应的字符,以便于操作;电梯请求展示区需要再细化,分别显示:向上请求、向下请求,电梯内请求。很漂亮,不过展示的信息太少3-1用户界面(2)电梯内部描述3-2自动机模型思考:该图有什么待改进之处?3-3全局变量函数之间如何通信?-全局变量或者参数线程之间如何通信?-全局变量或者参数全局变量设计考虑要全面;应明确给出定义,如:intdestLayer;//记录电梯下一目标服务楼层3-4程序模块化应该说明程序的模块结构,包括:整个程序分成哪几个文件?每一个文件里面包含哪些函数?函数原型说明?图示说明函数调用关系。要进行清楚的描述。3-5关键算法给出调度算法设计算法思路要有助于进一步设计,不能很粗略提纲1.使用线程实现任务并发2.模块化和工程3.概要设计要点4.时间控制函数5.有限状态自动机解题4.1-计时函数while(1){state_trans();();//根据自动机模型决定此刻电梯的状态print_message();/*输出电梯此刻的状态*/
control();/*根据控制策略确定下一目标楼层,这在 state_trans()中要用到*/
time_count();/*时间片推进一个*/}}4.1-计时函数clock_tclock(void);
ANSI标准库中的time.h头文件,其中定义了日期和时间的处理函数。
这个函数返回从“启动程序”到“程序中调用clock()函数”之间的CPU时钟计时单元(clocktick)数,在MSDN中称之为挂钟时间(wal-clock)。其中clock_t是用来保存时间的数据类型,长整型。clocktick:CPU时钟计时单元,时间长短由CPU控制。一个clocktick不是CPU的一个时钟周期,而是C/C++的一个基本计时单位。常量CLOCKS_PER_SEC,它表示一秒钟会有多少个时钟计时单元
。可以使用公式clock()/CLOCKS_PER_SEC来计算一个进程自身的运行时间。4.1-计时函数 #include“stdio.h”
#include“stdlib.h”
#include“time.h”
intmain(void)
{
long
i=10000000L;
clock_tstart,finish;
double
duration;
/*测量一个事件持续的时间*/
printf(“Timetodo%ldemptyloopsis”,i);
start=clock();
while(i--)
;//什么都不做
finish=clock();
duration=(double)(finish-start)/CLOCKS_PER_SEC;
printf("%fseconds\n",duration);
system("pause");
}4.1-计时函数下述循环将持续运行1秒钟clock_tstart,finish;double
duration;start=clock();duration=0.0;while(duration<1.0){
finish=clock();duration=(double)(finish-start)/CLOCKS_PER_SEC;}4.2-线程休眠函数
线程休眠函数:sleep(int);sleep(1000)Windows下表示1000毫秒,也就是1秒钟;Linux下表示1000秒,Linux下使用毫秒级别的函数可以使用usleep。
sleep函数是使调用sleep函数的线程休眠,线程主动放弃时间片。当经过指定的时间间隔后,再启动线程,继续执行代码。Sleep函数并不能起到定时的作用,主要作用是延时。#include<stdio.h>#include<windows.h>//注意头文件一定要包含intmain(){ inti=9; while(i>1){
sleep(1000);//线程被挂起1秒,相当于机器运行到这里停顿1秒,再继续向下运行;
printf("A"); i--;} system("pause");
return0;}4.3-Egg定时器1intWaitFor(unsignedintuMillisecond);这是一种很简单的定时器。调用此函数后,你的程序在uMillisecond毫秒内将什么也不做,静静地等待WaitFor()函数的返回。在需要延时的场合,这个函数是很好用的。但当用户关闭窗口的时候,它会立即返回,返回值为0。此时,我们要停止正在做的事情,转入退出流程。
例://让5个egg分别移动 #include“egg.h” //先定义5个egg
i=0; while(WaitFor(100)){SetActiveEgg(hEggs[i]);OffsetEgg((NUMBER_OF_EGG-i-1)*0.1,0);if(i<NUMBER_OF_EGG-1)i++;elsei=0;}4.4-Egg定时器2voidStartTimer(unsignedintuMillisecond);voidStopTimer(void);这两个函数比WaitFor()稍微复杂一点儿,但它们的控制能力更精准,而且可以和其它输入完全配合(WaitFor()在等待的时候,用户的所有输入动作都无效,除了关闭窗口)。StartTimer()后,每隔uMillisecond毫秒,都会产生一个TIMER事件,可以用WaitForEvent()得到这个事件,进而做相应的周期工作。不再需要定时事件时,调用StopTimer()停止它。
4.4-Egg定时器2EVENT_TYPEev;
......StartTimer(500);while((ev=WaitForEvent())
!=EXIT){switch(ev){caseTIMER://响应周期事件break;caseKEYDOWN://响应按键按下事件break;caseKEYUP://响应按键抬起事件break;}}StopTimer();
建议:定时器函数可以用在动画输出部分,控制对电梯画面的刷新。提纲1.使用线程实现任务并发2.模块化和工程3.概要设计要点4.时间控制函数5.有限状态自动机解题5.有限状态自动机解题第一步:画出状态转换图第二步:针对每一种状态,进一步分别分析:当输入为字符1时,需要做什么工作,下一个状态是什么如删除注释一题中要做的工作就是往目标文件中写入非注释部分的字符;当输入为字符2时,需要做什么工作,下一个状态是什么;…第三步:编码。将要做的工作和状态的迁移用代码表示出来练习:输入一个字
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2026年湖南软件职业技术大学单招职业适应性测试备考试题及答案解析
- 2026年河南中医药大学单招职业适应性考试备考试题及答案解析
- 2026年宣城职业技术学院单招职业适应性测试备考试题及答案解析
- 2026年重庆工程职业技术学院单招职业适应性测试备考试题及答案解析
- 2026年南昌工学院单招职业适应性测试备考试题及答案解析
- 期中家长会学生发言稿
- 2026年上海应用技术大学单招职业适应性考试备考题库及答案解析
- 2026年达州中医药职业学院单招职业适应性测试备考题库及答案解析
- 2026年仰恩大学单招职业适应性考试模拟试题及答案解析
- 2026年江苏护理职业学院单招职业适应性测试参考题库及答案解析
- 公路工程试验检测实施细则22
- 阿司匹林肠溶片
- 2024包头轻工职业技术学院工作人员招聘考试试题及答案
- 海上应急搜救预案
- 劳动合同涨工资协议
- 2025年内蒙古执业药师继续教育答案(一)
- 2025年师德师风工作总结
- 网络安全知识培训教程课件
- 膝骨关节炎中西医结合诊疗指南
- 《CRTAS-2024-06 互联网租赁自行车停放区设置指南》
- 云南省曲靖市麒麟区2023年小升初数学试卷
评论
0/150
提交评论