程序設(shè)計(jì)實(shí)踐6w 線程、時(shí)間函數(shù)和設(shè)計(jì)問題_第1頁
程序設(shè)計(jì)實(shí)踐6w 線程、時(shí)間函數(shù)和設(shè)計(jì)問題_第2頁
程序設(shè)計(jì)實(shí)踐6w 線程、時(shí)間函數(shù)和設(shè)計(jì)問題_第3頁
程序設(shè)計(jì)實(shí)踐6w 線程、時(shí)間函數(shù)和設(shè)計(jì)問題_第4頁
程序設(shè)計(jì)實(shí)踐6w 線程、時(shí)間函數(shù)和設(shè)計(jì)問題_第5頁
已閱讀5頁,還剩46頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

線程、設(shè)計(jì)問題提綱1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)2.模塊化和工程3.概要設(shè)計(jì)要點(diǎn)4.時(shí)間控制函數(shù)5.有限狀態(tài)自動(dòng)機(jī)解題1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)問題的引出:以電梯控制系統(tǒng)為例目前能想到的程序主體結(jié)構(gòu)main(){while(1){get_input();//接收電梯服務(wù)請求state_trans();//計(jì)算此刻電梯的狀態(tài)print_message();//輸出電梯此刻的狀態(tài)time_count();//時(shí)間片推進(jìn)一個(gè)}}思考:上述結(jié)構(gòu)不合理之處?

31.使用線程實(shí)現(xiàn)任務(wù)并發(fā)上述結(jié)構(gòu)不合理之處:必須接收服務(wù)請求后才能輸出電梯狀態(tài),與現(xiàn)實(shí)中的電梯運(yùn)行不符!程序結(jié)構(gòu)的改進(jìn): 從上述代碼中刪除get_input(),從而實(shí)現(xiàn)每隔一小段時(shí)間就刷新電梯當(dāng)前狀態(tài)main(){while(1){state_trans();//計(jì)算此刻電梯的狀態(tài)print_message();//輸出電梯此刻的狀態(tài)time_count();//時(shí)間片推進(jìn)一個(gè)}}41.使用線程實(shí)現(xiàn)任務(wù)并發(fā)但是,程序必須要能接收電梯服務(wù)請求,如何處理服務(wù)請求的輸入?理想狀態(tài):電梯服務(wù)請求的接收和電梯狀態(tài)的計(jì)算輸出能同時(shí)進(jìn)行,互不影響但是,能否實(shí)現(xiàn)?答案是:使用線程電梯狀態(tài)計(jì)算和輸出共享內(nèi)存區(qū)接收服務(wù)請求51.使用線程實(shí)現(xiàn)任務(wù)并發(fā)進(jìn)程一個(gè)獨(dú)立程序的每一次運(yùn)行稱為一個(gè)進(jìn)程,例如用字處理軟件編輯文稿時(shí),同時(shí)打開mp3播放程序聽音樂,這兩個(gè)獨(dú)立的程序在同時(shí)運(yùn)行,稱為兩個(gè)進(jìn)程進(jìn)程是計(jì)算機(jī)資源分配的基本單位。設(shè)置一個(gè)進(jìn)程要占用相當(dāng)一部分處理器時(shí)間和內(nèi)存資源大多數(shù)操作系統(tǒng)不允許進(jìn)程訪問其他進(jìn)程的內(nèi)存空間,進(jìn)程間的通信很不方便,編程模型比較復(fù)雜1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)線程一個(gè)程序中多段代碼同時(shí)并發(fā)執(zhí)行,稱為多線程通過多線程,一個(gè)進(jìn)程表面上看同時(shí)可以執(zhí)行一個(gè)以上的任務(wù)——并發(fā)線程是被系統(tǒng)獨(dú)立調(diào)度和分派的基本單位。進(jìn)程用來分配資源,實(shí)際運(yùn)行的是線程,每個(gè)進(jìn)程至少包含一個(gè)線程。同一進(jìn)程中的多個(gè)線程之間可以并發(fā)執(zhí)行線程自己不擁有系統(tǒng)資源,但它可與同屬一個(gè)進(jìn)程的其它線程共享進(jìn)程所擁有的全部資源1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)在C程序中要?jiǎng)?chuàng)建線程,可以調(diào)用Windows操作系統(tǒng)提供的創(chuàng)建線程的函數(shù)CreateThread:HANDLE

CreateThread(

LPSECURITY_ATTRIBUTES

lpThreadAttributes,

DWORD

dwStackSize,

LPTHREAD_START_ROUTINE

lpStartAddress,

LPVOID

lpParameter,

DWORD

dwCreationFlags,

DWORD

lpThreadId);

LPVOID是一個(gè)Void類型的指針,也就是說你可以將任意類型的指針賦值給LPVOID類型的變量。DWORD是32位無符號整數(shù)。1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)lpThreadAttributes表示創(chuàng)建線程的安全屬性,NT下有用??少x值為NULL。dwStackSize指定線程棧的尺寸,如果為0則與進(jìn)程主線程棧相同。lpStartAddress指定線程開始運(yùn)行的地址。賦值為指向函數(shù)的指針,即函數(shù)名。lpParameter表示傳遞給線程的32位的參數(shù)。若無參數(shù)則賦值為NULL。dwCreationFlags表示是否創(chuàng)建后掛起線程(取值CREATE_SUSPEND),掛起后調(diào)用ResumeThread繼續(xù)執(zhí)行。若不掛起則賦值為0。lpThreadId用來存放返回的線程ID。DWORDThreadID1=1;HANDLEhRead1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput, NULL,0,&ThreadID1);1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)1.使用線程實(shí)現(xiàn)任務(wù)并發(fā) main函數(shù)中創(chuàng)建兩個(gè)線程,線程1從鍵盤接收字符數(shù)據(jù)寫入變量ch中,線程2讀取ch寫入文件中。1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)#include<stdio.h>#include<stdlib.h>//使用線程編程時(shí),下面這兩個(gè)頭文件必須包含#include<winsock.h>#include<winbase.h>voidgetInput(void);//線程1要運(yùn)行的函數(shù)voidoutput(void);//線程2要運(yùn)行的函數(shù)charch=‘A’;//全局變量1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)intmain(){inti;

/*創(chuàng)建線程1:從鍵盤接收字符寫入到全局變量ch中*/DWORDThreadID1=1;HANDLEhRead1=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput,NULL,0,&ThreadID1);

/*創(chuàng)建線程2:用于將全局變量ch寫入文件*/DWORDThreadID2=2;HANDLEhRead2=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)output,NULL,0,&ThreadID2);

1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)while(1){/*死循環(huán)。本循環(huán)必須要有,否則main函數(shù)一結(jié)束,另兩個(gè)線程也就結(jié)束了。*/}system("PAUSE"); return0;}1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)voidgetInput(void){inti;

while(1){printf("inputachar\n");ch=getchar();fflush(stdin);//使回車不被讀取}}1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)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);//確保不關(guān)閉文件情況下數(shù)據(jù)能寫入}}信號量例子問題字符被重復(fù)寫入多次如何解決線程間采用信號量進(jìn)行同步控制線程在電梯控制系統(tǒng)中的使用考慮現(xiàn)實(shí)中安裝在電梯上的軟件:接收電梯服務(wù)請求和計(jì)算電梯狀態(tài)、從而控制電梯的運(yùn)行是并行的因此我們可以考慮在模擬電梯控制系統(tǒng)中設(shè)計(jì)一個(gè)線程專門用于接收電梯服務(wù)請求,另一個(gè)線程實(shí)行電梯的狀態(tài)計(jì)算和狀態(tài)輸出電梯狀態(tài)計(jì)算和輸出線程共享內(nèi)存區(qū)接收服務(wù)請求電梯狀態(tài)計(jì)算和輸出:從共享內(nèi)存區(qū)讀取電梯請求,計(jì)算下一目標(biāo)樓層,從而確定電梯的下一狀態(tài)。接收服務(wù)請求:接收電梯請求,將請求保存到內(nèi)存。//主線程main(){DWORDThreadID=1;//創(chuàng)建線程(對應(yīng)于函數(shù)input()),用于接收電梯輸入;HANDLEhRead=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)getInput,NULL,0,&ThreadID);

//進(jìn)行變量初始化工作

線程在電梯控制系統(tǒng)中的使用while(1){state_trans();();//根據(jù)自動(dòng)機(jī)模型決定此刻電梯的狀態(tài)print_message();/*輸出電梯此刻的狀態(tài)*/

control();/*根據(jù)控制策略確定下一目標(biāo)樓層,這在 state_trans()中要用到*/time_count();/*時(shí)間片推進(jìn)一個(gè)*/}}線程在電梯控制系統(tǒng)中的使用//接收輸入線程voidgetInput(void){charch;while(1){ ch=getchar();//加入代碼:將ch翻譯成相應(yīng)請求并保存;time_count();//時(shí)間片推進(jìn)一個(gè);}}線程在電梯控制系統(tǒng)中的使用提綱1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)2.模塊化和工程3.概要設(shè)計(jì)要點(diǎn)4.時(shí)間控制函數(shù)5.有限狀態(tài)自動(dòng)機(jī)解題2.模塊化和工程模塊的定義一般把用一個(gè)名字就可調(diào)用的一段程序稱為“模塊”,如子程序、函數(shù)等。模塊的基本屬性:功能:描述該模塊實(shí)現(xiàn)什么功能邏輯:描述模塊內(nèi)部怎么做狀態(tài):該模塊使用時(shí)的環(huán)境和條件除了基本屬性,還需描述模塊的內(nèi)部和外部特性模塊的外部特性:模塊的模塊名、參數(shù)表模塊的內(nèi)部特性:完成其功能的程序代碼和僅供該模塊內(nèi)部使用的數(shù)據(jù)通常是先確定模塊的外部特性,再確定其內(nèi)部特性。2.模塊化和工程函數(shù)是最小的模塊,若干個(gè)緊密相關(guān)的函數(shù)可以組成更大的模塊--源文件。一條好的原則就是保持模塊的緊湊性.即在同一個(gè)源文件中只包含那些在邏輯上與其相關(guān)的函數(shù)。2.模塊化和工程模塊化:把程序劃分成獨(dú)立命名且可獨(dú)立訪問的模塊,每個(gè)模塊完成一個(gè)子功能,所有模塊集成起來構(gòu)成的整體可完成用戶的所有需求。模塊化意義降低了系統(tǒng)的復(fù)雜性,使系統(tǒng)容易修改和重用;推動(dòng)系統(tǒng)各部分的并行開發(fā),提高開發(fā)效率。使用工程來組織多個(gè)源文件。將功能緊密相關(guān)的若干個(gè)函數(shù)組成單獨(dú)的源文件。復(fù)雜問題較小問題高層模塊從整體上把握問題,隱蔽細(xì)節(jié)分解提綱1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)2.模塊化和工程3.概要設(shè)計(jì)要點(diǎn)4.時(shí)間控制函數(shù)5.有限狀態(tài)自動(dòng)機(jī)解題3.概要設(shè)計(jì)要點(diǎn)概要設(shè)計(jì)的目的:全局把握程序結(jié)構(gòu):進(jìn)行程序的模塊劃分,設(shè)計(jì)模塊之間如何相互調(diào)用來完成程序要求的功能。定義關(guān)鍵變量,用來存儲各模塊共享的數(shù)據(jù);定義常量。設(shè)計(jì)關(guān)鍵的算法,主要是控制策略,提前對關(guān)鍵的、較難解決的問題進(jìn)行處理。3.概要設(shè)計(jì)要點(diǎn)概要設(shè)計(jì)主要從以下5個(gè)方面考慮:用戶界面:界面友好,要能從界面提示信息了解電梯/火車/銀行的狀態(tài)和請求。自動(dòng)機(jī)模型:有自動(dòng)機(jī)狀態(tài)遷移圖,狀態(tài)遷移圖上描述了引起狀態(tài)遷移的條件,并且要在文檔中附加說明進(jìn)入某狀態(tài)要做的動(dòng)作。全局變量:較全面地給出了各個(gè)函數(shù)要共享的數(shù)據(jù)。程序模塊化:函數(shù)接口說明,函數(shù)調(diào)用關(guān)系說明。調(diào)度算法:給出電梯、小火車調(diào)度或者銀行調(diào)度的算法。3-1用戶界面(1)點(diǎn)評:界面上增加各層向上向下請求對應(yīng)的字符,以便于操作;電梯請求展示區(qū)需要再細(xì)化,分別顯示:向上請求、向下請求,電梯內(nèi)請求。很漂亮,不過展示的信息太少3-1用戶界面(2)電梯內(nèi)部描述3-2自動(dòng)機(jī)模型思考:該圖有什么待改進(jìn)之處?3-3全局變量函數(shù)之間如何通信?-全局變量或者參數(shù)線程之間如何通信?-全局變量或者參數(shù)全局變量設(shè)計(jì)考慮要全面;應(yīng)明確給出定義,如:intdestLayer;//記錄電梯下一目標(biāo)服務(wù)樓層3-4程序模塊化應(yīng)該說明程序的模塊結(jié)構(gòu),包括:整個(gè)程序分成哪幾個(gè)文件?每一個(gè)文件里面包含哪些函數(shù)?函數(shù)原型說明?圖示說明函數(shù)調(diào)用關(guān)系。要進(jìn)行清楚的描述。3-5關(guān)鍵算法給出調(diào)度算法設(shè)計(jì)算法思路要有助于進(jìn)一步設(shè)計(jì),不能很粗略提綱1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)2.模塊化和工程3.概要設(shè)計(jì)要點(diǎn)4.時(shí)間控制函數(shù)5.有限狀態(tài)自動(dòng)機(jī)解題4.1-計(jì)時(shí)函數(shù)while(1){state_trans();();//根據(jù)自動(dòng)機(jī)模型決定此刻電梯的狀態(tài)print_message();/*輸出電梯此刻的狀態(tài)*/

control();/*根據(jù)控制策略確定下一目標(biāo)樓層,這在 state_trans()中要用到*/

time_count();/*時(shí)間片推進(jìn)一個(gè)*/}}4.1-計(jì)時(shí)函數(shù)clock_tclock(void);

ANSI標(biāo)準(zhǔn)庫中的time.h頭文件,其中定義了日期和時(shí)間的處理函數(shù)。

這個(gè)函數(shù)返回從“啟動(dòng)程序”到“程序中調(diào)用clock()函數(shù)”之間的CPU時(shí)鐘計(jì)時(shí)單元(clocktick)數(shù),在MSDN中稱之為掛鐘時(shí)間(wal-clock)。其中clock_t是用來保存時(shí)間的數(shù)據(jù)類型,長整型。clocktick:CPU時(shí)鐘計(jì)時(shí)單元,時(shí)間長短由CPU控制。一個(gè)clocktick不是CPU的一個(gè)時(shí)鐘周期,而是C/C++的一個(gè)基本計(jì)時(shí)單位。常量CLOCKS_PER_SEC,它表示一秒鐘會有多少個(gè)時(shí)鐘計(jì)時(shí)單元

??梢允褂霉絚lock()/CLOCKS_PER_SEC來計(jì)算一個(gè)進(jìn)程自身的運(yùn)行時(shí)間。4.1-計(jì)時(shí)函數(shù) #include“stdio.h”

#include“stdlib.h”

#include“time.h”

intmain(void)

{

long

i=10000000L;

clock_tstart,finish;

double

duration;

/*測量一個(gè)事件持續(xù)的時(shí)間*/

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-計(jì)時(shí)函數(shù)下述循環(huán)將持續(xù)運(yùn)行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-線程休眠函數(shù)

線程休眠函數(shù):sleep(int);sleep(1000)Windows下表示1000毫秒,也就是1秒鐘;Linux下表示1000秒,Linux下使用毫秒級別的函數(shù)可以使用usleep。

sleep函數(shù)是使調(diào)用sleep函數(shù)的線程休眠,線程主動(dòng)放棄時(shí)間片。當(dāng)經(jīng)過指定的時(shí)間間隔后,再啟動(dòng)線程,繼續(xù)執(zhí)行代碼。Sleep函數(shù)并不能起到定時(shí)的作用,主要作用是延時(shí)。#include<stdio.h>#include<windows.h>//注意頭文件一定要包含intmain(){ inti=9; while(i>1){

sleep(1000);//線程被掛起1秒,相當(dāng)于機(jī)器運(yùn)行到這里停頓1秒,再繼續(xù)向下運(yùn)行;

printf("A"); i--;} system("pause");

return0;}4.3-Egg定時(shí)器1intWaitFor(unsignedintuMillisecond);這是一種很簡單的定時(shí)器。調(diào)用此函數(shù)后,你的程序在uMillisecond毫秒內(nèi)將什么也不做,靜靜地等待WaitFor()函數(shù)的返回。在需要延時(shí)的場合,這個(gè)函數(shù)是很好用的。但當(dāng)用戶關(guān)閉窗口的時(shí)候,它會立即返回,返回值為0。此時(shí),我們要停止正在做的事情,轉(zhuǎn)入退出流程。

例://讓5個(gè)egg分別移動(dòng) #include“egg.h” //先定義5個(gè)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定時(shí)器2voidStartTimer(unsignedintuMillisecond);voidStopTimer(void);這兩個(gè)函數(shù)比WaitFor()稍微復(fù)雜一點(diǎn)兒,但它們的控制能力更精準(zhǔn),而且可以和其它輸入完全配合(WaitFor()在等待的時(shí)候,用戶的所有輸入動(dòng)作都無效,除了關(guān)閉窗口)。StartTimer()后,每隔uMillisecond毫秒,都會產(chǎn)生一個(gè)TIMER事件,可以用WaitForEvent()得到這個(gè)事件,進(jìn)而做相應(yīng)的周期工作。不再需要定時(shí)事件時(shí),調(diào)用StopTimer()停止它。

4.4-Egg定時(shí)器2EVENT_TYPEev;

......StartTimer(500);while((ev=WaitForEvent())

!=EXIT){switch(ev){caseTIMER://響應(yīng)周期事件break;caseKEYDOWN://響應(yīng)按鍵按下事件break;caseKEYUP://響應(yīng)按鍵抬起事件break;}}StopTimer();

建議:定時(shí)器函數(shù)可以用在動(dòng)畫輸出部分,控制對電梯畫面的刷新。提綱1.使用線程實(shí)現(xiàn)任務(wù)并發(fā)2.模塊化和工程3.概要設(shè)計(jì)要點(diǎn)4.時(shí)間控制函數(shù)5.有限狀態(tài)自動(dòng)機(jī)解題5.有限狀態(tài)自動(dòng)機(jī)解題第一步:畫出狀態(tài)轉(zhuǎn)換圖第二步:針對每一種狀態(tài),進(jìn)一步分別分析:當(dāng)輸入為字符1時(shí),需要做什么工作,下一個(gè)狀態(tài)是什么如刪除注釋一題中要做的工作就是往目標(biāo)文件中寫入非注釋部分的字符;當(dāng)輸入為字符2時(shí),需要做什么工作,下一個(gè)狀態(tài)是什么;…第三步:編碼。將要做的工作和狀態(tài)的遷移用代碼表示出來練習(xí):輸入一個(gè)字

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論