可编程控制器期末总结

2024-06-30

可编程控制器期末总结(共9篇)(共9篇)

1.可编程控制器期末总结 篇一

通过本课程的学习,我们可以获得电气控制与可编程控制器的基本知识和基本技能,培养分析和解决实际问题的能力,并为今后从事电气工程领域的技术工作打下基础。如果以后从事电气原理图的设计与选型这一工作,这么门课是很重要的.因为电气最终实现动作还是通过编程来实现的。这本书包括两方面

1、电器控制部分。该部分主要掌握继电器控制电路的分析、设计,能够了解各类继电器的工作原理,利用继电器组成电动机的启动、自保、调速、制动控制电路,掌握控制线路的设计原则、基本规律以及一般设计方法。

2、可编程序控制器部分(即PLC部分)。该部分主要掌握三菱FX2N系列的原理、基本指令、基本指令的编程方法、设计控制线路、部分功能指令的使用方法。掌握一种三菱编程软件。第一章

常用低压电器

1.本章重点介绍继电器-接触器控制系统中常用的低压电器。这些常用低压电器是组成控制电路的重要的元件。

2低压电器是在交流电压为1200V,直流电压为1500V及以下的电路中起通断、保护、控制、变换、检测、或调节作用的基本元件。

第二章

电气控制线路的基本规律

1.电气控制线路图绘制原则及读图方法:按国家统一规定的电气图形符号和文字符号。

2.学习由电器元件组成的三相交流异步电动机的启动、停止,正反转,多地,多条件控制电路的基本原理;降压起动控制电路;制动控制电路;调速。

第三章 电气控制系统分析 1CA6140车床电气控制线路分析 X-62W 型万能铣床:X-62W 卧式万能铣床主轴采用反接制动,变速时有短时冲动,机械操作手柄与行程开关、机械挂档的操作控制及三个方向进给之间具有联锁关系。

第四章电气控制系统的设计

1电气控制线路设计的一般原则:

(一)最大限度地实现生产机械和工艺对电气控制线

路的要求

(二)在满足生产要求的前提下,力求使控制线路简 单、经济。

2:电气控制线路两种设计方法:经验设计法,逻辑代数设计法 第五章可编程控制器的概述 PLC是一种专门为在工业环境下应用而设计的数字运算操作的电子装置。

2可编程控制器的应用领域:开关量的逻辑控制,模拟量控制,运动控制,过程控制,数据处理,通信及联网 PLC的组成:由中央处理器(CPU)、存储器(RAM、ROM)、输入输出器件(I/O接口)、电源及编程设备构成: 4可编程控制器的工作原理:在系统程序的管理下,通过运行应用程序完成用户任务

第六章

三菱FX2N系列可编程控制器及其基本指令的应用 1.FX2N系列可编程控制器软组件:

输入继电器:X;

输出继电器:Y;

辅助继电器:M

状态继电器:S;

定时器: T;

计数器:C;

数据寄存器D;

指针:P、I、N 2.FX2N基本指令:逻辑取及线圈驱动指令,触点串联(AND、ANI)指令,触点并联(OR、ORI)指令,脉冲指令,串联电路快的并联(ORB)指令,并联电路块串联(ANB)指令 第七章

FX2N系列PLC步进指令 及状态编程法

本章介绍状态指令、状态元件、状态三要素、状态编程思想,状态转移图与状态梯形图对应关系。然后说明常见状态转移图的编程方法,并结合实例介绍状态编程思想在顺序控制中的应用。第八章FX2N系列PLC的应用指令及编程方法

应用指令是可编程控制器数据处理能力的标志。由于数据处理远比逻辑处理复杂,应用指令无论从梯形图的表达形式上,还是从涉及的机内器件种类及信息的数量上都有一定的特殊性。

第九章可编程控制系统设计

一、PLC控制系统设计的基本原则 1).最大限度地满足被控对象的控制要求。

2)在满足控制要求前提下,力求使控制系统简单、经济使用及维修方便。

3)保证控制系统安全、可靠、稳定。

4)考虑到生产的发展和工艺的更改,选择PLC容量要适当留有裕度。

2. PLC控制系统设计的基本内容

1)选择用户输入设备(按钮、操作开关、限位开关、传感器)、输出设备(接触器、信号灯、继电器等执行元件)以及由输出设备驱动的控制对象(电动机、电磁阀等)。

2)选择PLC(型号、容量、I/O模块、电源模块等的选择)。3)分配I/O点,绘制I/O接线图。

4)设计控制程序。包括有系统流程图、梯形图、语句表。5)必要时还需设计控制台柜(此项一般由机械技术人员设计)。6)编制控制系统的技术文件。包括有说明书、电气图及电气元件明细表等。

第十章 FX2n系列PLC的特殊功能模块及通信

本章着重介绍三菱公司FX2n系列PLC某些特殊功能模块主要性能,线路连接以及PLC的通信作介绍,如模拟量输入模块 FX2N-4AD、模拟量输出模块 FX2N-4DA。

随著微电脑的发展,PLC功能将更加强大,未来需要这方面的人才更多。对于我们学习电气的,这门可更要去学好。由于上课时间有限,自己学习能力还有待于加强,关于这门课以后还需要我们多花点时间去多翻翻书。否则一旦踏上工作岗位会有“书到用时方很少” 的悔感,那是我们就后悔也莫及了,所以一定要在毕业之前掌握好各门专业课。最后真心要感谢老师,不仅是教了我们这门课,更多的是一种敬佩。我们上课的时候,由于这是一门考查课,很多同学都很放松,教室里吵杂。但是老师总是会把该讲的都讲到,不会因为某些同学不想学就不教,教学严谨,认真负责。

2.C语言期末考试编程题范文 篇二

int a,b,c,s,i=0;

for(s=100;s<1000;s++)

{

c=s%10;

b=s/10%10;

a=s/100;

if(s==a*a*a+b*b*b+c*c*c)

{

printf(“%dt”,s);

++i;

if(i%5==0)

printf(“n”);

}

} } 2.求1+2!+3!+...+20!的和 #include void main(){ double fact=1.0,sum=0.0;int i,j;for(i=1;i<=20;i++){ for(j=1;j<=i;j++)fact*=j;sum+=fact;fact=1;} printf(“%.0fn”,sum);} 3.输入一个5位数,判断它是不是回文数。即12321是回文数,个位与万位相同,十位与千位相同。#include #include void main(){ long num;int a,b,c,d;printf(“Please input the number:”);scanf(“%d”,&num);if(num<=9999||num>=100000){ printf(“%The number error!n”);exit(0);} a=num/10000;b=num/1000%10;c=num/10%10;d=num%10;if(a==d&&b==c)printf(“nYes,the %ld palindrome!n”,num);else

is is printf(“nNo,the %ld is not palindrome!n”,num);} 4.求出1到1000之内能被7或11整除、但不能同时被7和11整除的所有整数并并按照一行5个的格式输出。

#include void main(){ int num,i=0;for(num=1;num<=1000;num++)

if(((num%7||num%11)==1)&&((num%7&&num%11)==0)){ printf(“%dt”,num);++i;if(i%5==0)printf(“n”);} } 5.编程列出200以内所有的素数,按照一行10个的格式输出,并求出所有素数的平均值,#include #include void main(){ int i,j,k=0,sum=0,avg=0;for(i=2;i<200;i++){ for(j=2;j<=sqrt(i);j++)if(i%j==0)break;if(j>sqrt(i)){ printf(“%dt”,i);++k;sum+=i;if(k%10==0)printf(“n”);} } avg=sum/k;printf(“nThe is %dn”,avg);}

average

6、编写一个函数,输入n为偶数时,调用函数求1/2+1/4+...+1/n,当输入n为奇数时,调用函数1+1/3+1/5...+1/n #include void main(){ void odd(int n);void even(int n);int n;printf(“Please input the number:”);scanf(“%d”,&n);if(n%2)odd(n);else even(n);} void odd(int n){ float sum=0.0;float j;int i;for(i=1;i<=n;i+=2){ j=1.0/i;sum+=j;} printf(“%fn”,sum);} void even(int n){ float sum=0.0;int i;float j;if(n==0)printf(“%fn”,sum);else { for(i=2;i<=n;i+=2){ j=1.0/i;sum+=j;} printf(“%fn”,sum);} }

7、已知abc+cba=1333,其中a,b,c均为一位数,编程求出满足条件的a,b,c所有 组合。

#include void main(){ int a,b,c;for(a=1;a<=9;a++)for(b=0;b<=9;b++)for(c=1;c<=9;c++)

if((100*a+10*b+c+100*c+10*b+a)==1333)

printf(“a=%d,b=%d,c=%dn”,a,b,c);}

8、用户输入12个0-100之间的整数,统计出小于60,60到79,80到100三个范围的整数各有多少个? #include #include void main(){ int i,j,k,n,num;i=j=k=0;printf(“Please input the 12 numbers with 0~100:”);for(n=1;n<=12;n++){ scanf(“%d”,&num);if(!(num>=0&&num<=100))exit(0);if(num<60)++i;else if(num<80)++j;else ++k;} printf(“nThere

are

%d numbers less than 60,%d numbers between 60 and 79,%d numbers between 80 and 100.n”,i,j,k);}

9、求这样一个三位数并输出该数字,该三位数等于其每位数字的阶乘之和。

即: abc = a!+ b!+ c!#include void main(){ int a,b,c,num;int s(int);for(num=100;num<1000;num++){ a=num/100;b=num/10%10;c=num%10;if(num==s(a)+s(b)+s(c)){ printf(“The is %dn”,num);break;} } } s(int n){ int i,sum=1;for(i=1;i<=n;i++)sum*=i;

number return sum;}

10、猜数游戏:由用户随机输入一个1位正整数数让人来猜,只能猜5次,如果人猜对了,则在屏幕上显示“You are so clever”,否则计算机给出提示,告诉人所猜的数是太大还是太小,直到人猜对为止或者5次都猜不对给出提示“Game Over”。#include #include void main(){ int num,i,n;printf(“Please input the number with 0~9 for guessing:”);scanf(“%d”,&num);system(“cls”);if(num<0||num>9)exit(0);for(i=1;i<=5;i++){ printf(“nPlease input the number you guess:”);scanf(“%d”,&n);if(num==n){ printf(“nYou are so clever!n”);break;} else if(n

have

%d

times left!n”,5-i);continue;} else { printf(“nThe number you input is large,go on please!You

have

%d

times left!n”,5-i);continue;} } if(i>5)Over!n“);}

11、设N是一个四位数,它的9倍恰好是其反序数(例如:123的反序数是321),求N的值。#include void main(){ int n,k,a,b,c,d;for(n=1000;n<=9999;n++){ a=n/1000;

printf(”Game b=n/100%10;c=n/10%10;d=n%10;k=1000*d+100*c+10*b+a;if(k==9*n)printf(“N=%dn”,n);} } 12、100匹马驮100担货,大马一匹驮3担,中马一匹驮2担,小马两匹驮1担。试编写程序计算大、中、小马的数目。#include void main(){ int h1,h2,h3;for(h1=0;h1<=100;h1++)for(h2=0;h2<=100;h2++)for(h3=0;h3<=100;h3+=2){

if(h1+h2+h3==100&&3*h1+2*h2+1/2*h3==100)printf(“The horse has has

%d,middle

old horse horse

%d,young has %dn”,h1,h2,h3);} }

13、一位司机酒驾撞人逃跑。现场三人目击事件,但都没记住车号,只记下车号的一些特征。甲说:牌照的前两位数字是相同的;乙说:牌照的后两位数字是相同的;丙是位数学家,他说:四位的车号刚好是一个整数的平方。请根据以上线索求出车号。(车号为4位数)#include #include void main(){ int n,a,b,c,d,i;for(n=1000;n<=9999;n++){ a=n/1000;b=n/100%10;c=n/10%10;d=n%10;i=sqrt(n);if(a==b&&c==d&&i*i==n)printf(“%dn”,n);} } 14、求S=1/(1*2)+1/(2*3)+1/(3*4)+……前50项之和并输出结果。#include void main(){ float i;float s=0;for(i=1;i<51;i++)s+=1.0/(i*(i+1));printf(“%f”,s);}

15、编程求出所有1000到3000之间能被7、11、17同时整除的整数,并求其平均值,并输出结果(结果保留两位小数)。#include void main(){ int i,k=0,sum=0;for(i=1000;i<=3000;i++)if(i%7==0&&i%11==0&&i%17==0){ sum+=i;++k;printf(“%dt”,i);}

printf(“n%d”,sum/k);}

16、编程找出满足下列条件的所有四位数的和并输出:该数第一、三位数字之和为10,第二、四位数字之积为12。

#include #include int main(void){ int i,j,x,y,z,m;for(i = 1000;i< 10000;i++){ x = i/1000;y =(i/100)%10;z =(i/10)%10;m = i%10;if((x + z)==10&&(y+ m)==12){ printf(“%dt”,i);} } printf(“n”);return 0;}

17、求并输出所有满足如下条件的三位正整数:它是某整数的平方,它的三位数码有两位是相同的。(如100是10的平方,它有两个0,225是15的平方,它有两个2)。#include #include void main(){ int n,i,a,b,c;for(n=100;n<=999;n++){ a=n/100;b=n/10%10;c=n%10;i=sqrt(n);

if((a==b||a==c||b==c)&&n==i*i)printf(“%dt”,n);} }

18、输出所有大于1010的4位偶数,且该类偶数的各位数字两两不相同。#include void main(){ int num,a,b,c,d;

for(num=1012;num<=9999;num+=2){ a=num/1000;b=num/100%10;c=num/10%10;d=num%10;if(a!=b&&b!=c&&c!=d)printf(“%dt”,num);} }

19、编制程序要求输入整数a和b,若a+b大于100,则输出a+b百位以上的数字,否则输出两数字之和。#include 2

222void main(){ int a,b,s;printf(“Please input a and b:”);scanf(“%d%d”,&a,&b);s=a*a+b*b;if(s>100)printf(“n%dn”,s/100);else printf(“n%dn”,a+b);} 20、编写一个程序实现如下功能:计算1~100之间所有包含4或者包含5的数字,并显示其累加之和 #include void main(){ int a,b,i,sum=0;for(i=1;i<=99;i++){ a=i/10;b=i%10;

3.《可编程控制器》课程改革计划 篇三

可编程控制器课程是自动化专业的核心专业课,在学生从事自动化相关工作过程中,这门课的内容将影响到学生的工作能力,依据学院的要求和我系的课程改革计划,我们制定可编程控制器课程的改革计划。

一、课程小组组成课程小组负责人:杜俊贤

成员:刘道刚、姜虎强、范长青、王宁

二、企业调研

1、主要内容:可编程控制器小组成员,走访烟台万华聚氨酯股份有限公司、LG-浪潮电子有限公司、烟台国冶自动化有限公司、烟台德尔福汽车配件有限公司、烟台首钢有限公司、依诺特电子有限公司、烟台龙腾自动化公司共七家企业技术人员、优秀毕业生,了解企业对学生的需求,了解课程在实际岗位的应用情况,并撰写调研报告。

2、时间安排:2013年8月—10月

3、验收内容:企业调研报告。

三、课程改革试验

1、主要内容:课程改革小组根据企业调研意见确定课程改革的内容,切实开展相关工作,有计划、有步骤地完成课改试验。

2、时间安排:2013年10月—2014年1月

(1)2013年11月:第一阶段

初步完成“6〃2〃1”教学模式整体设计、“6〃2〃1”教学模式单元设计。

(2)2014年1月:第二阶段

完善“6〃2〃1”教学模式整体设计、“6〃2〃1”教学模式单元设计,在授课实践过程中,完善教学资源、编写自编教材。

四、总结评价

1、主要内容:对课改工作进行总体评价,总结经验教训,提出并实施整改措施;完善课改评价体系。

2、时间安排:2014年3月

五、全面推广阶段

1、主要内容:对课改试验项目进行全面推广,总结经验教训,形成理论体系。

2、时间安排:2014年3月—2014年7月

2014年5月:第三阶段全面推广阶段

根据改革后的课程,进行全面推广,并依据推广过程中的效果整理课改推广效果材料,学生评价材料和整改意见。

2014年7月:第四阶进一步整改。

依据第三阶段的整改意见,进一步整改课程,完善课程体系。

六、全面评价阶段

1、主要内容:对课改工作展开全面评价,将课改过程中所产生的教学模式改革、校本教材开发、校企合作等经验总结提炼,形成院级科研成果,为下一阶段教育教学改革提供理论依据。

2、时间安排:2014年8月

信息与控制工程系

4.可编程控制器期末总结 篇四

目的:掌握可编程控制器的原理,基础指令、程序设计,和基于PLC的控制系统设计方法,为后续学习打下基础。

一、版面格式:

1、读书报告名称应正确,如:

2、应体现自己的相关信息,必须正确。包括:系别、专业、班级、姓名、学号、任课教师、学年学期。

3、学习态度良好、字迹、版面应清洁,手写8000字左右,图、表全由手工完成。统一用“南阳理工学院稿纸”

二、可编程控制器技术概述:

1、可编程控制器的基本概念、发展

2、可编程控制器的特点和应用

3、常用可编程控制器种类

三、可编程控制器技术掌握情况:

1、PLC的基本组成,包括:主机、扩展、特殊功能元件、继电器区、数据区。

2、PLC的指令系统,包括:常用基本指令、应用指令、传送指令、数据指令、定时器、计数器等。

3、PLC的控制系统设计,包括:用实例解释至少4种设计方法。

四、可编程控制器技术的应用实例:结合自己掌握可编程控制器技术情况和兴趣自选一实例。包括有以下内容:

1、控制对象及要求

2、工程分析

3、PLC选型

4、I/O分配

5、电气原理图

6、程序设计需要体现设计方法

7、联机调试

五、读书总结:

总结:包括:学习过程、认识、开拓思考、以及对本课程的改进意见,专业创新等。

5.可编程序控制器在选煤厂的应用 篇五

赵立民

摘要 介绍了以可编程序控制器为核心的集控系统在选煤厂的应用,着重分析了该控制系统的硬件结构和软件设计思想,并对控制过程中出现的问题提出了改进意见。

关键词 可编程序控制器 集控系统 程序软件 引 言

黑岱沟露天矿选煤厂是年设计处理能力1200万t的大型选煤厂,主要由原煤破碎筛分、跳汰洗选和煤泥水等几个系统组成。该厂对这几个系统进行综合管理、协调生产的电气控制系统自动化程度较高,采用计算机和可编程序控制器(PLC)作为控制系统的核心,对全厂近400台设备实现了集中控制,统一管理。本文从设计角度介绍了该控制系统硬件和软件的构成特点以及实际使用情况。控制系统方案

2.1 硬件构成

选煤厂的生产工艺流程为:①毛煤仓中的原煤首先经过破碎筛分,筛下物直接进入产品煤仓,筛上物则进入跳汰系统;②跳汰机分选出矸石、中煤和块精煤,分别送入矸石仓和产品仓,同时精煤筛下物排入斗子捞坑,经离心机脱水后产出末精煤,也送入产品仓;③斗子捞坑的溢流自流进入浓缩池,池中下沉的煤泥水由底流泵打入压滤机处理,上部的澄清水则由循环泵注入跳汰机循环使用,形成洗水闭路循环系统。

控制系统的结构见图1。根据上述工艺流程特点,以生产设备为控制对象,集控系统设置了3个远程分站,对各分站内的设备分别进行控制。按照集中控制方式,可编程序控制系统由调度管理中心和过程控制单元两部分组成。

图1 计算机与PLC控制系统网络 2.1.1 调度管理中心

上位机采用IBM系列微机。作为管理级计算机,该机可实现对生产过程的实时监控,调度人员根据生产需要对运行设备进行调整时,通过计算机发出各种指令来完成;上位机也可对生产过程的主要数据进行统计、分析、处理,将结果在CRT上显示或打印输出。

上位机也是PLC的编程器,对可编程序控制器进行组态配置,离线编制系统的应用程序或在线修改梯形图逻辑程序,使PLC能够准确地控制设备。

大屏幕用于全面地显示生产系统的工艺流程和设备的运行状态。2.1.2 过程控制单元

下位机采用美国莫迪康公司984—785可编程序控制器,通过处理现场的反馈信号,对生产过程进行自动控制,并生成图文资料,供调度人员指挥生产。该PLC通过S908远程处理器与I/O模块构成高速远程I/O网络,最多可建立31个远程分站,可处理开关量点数达16384点,解算1K用户逻辑仅需1.5ms,而且可在恶劣的环境中可靠地运行。

各I/O功能块均选用莫迪康800系列模块,包括开关量模块(220VAC)和模拟量模块(4~20mA)。模块面板上均设有指示灯,显示模块的实际工作状态。所有模块都符合IEEE—472电冲击保护标准。

输入模块采集现场设备的状态信息并送入可编程序控制器,按照梯形图程序,984—785内部的CPU对输入数据进行逻辑运算,处理结果经输出模块输出,直接驱动交流接触器线圈或声光设备,实现了生产的自动化。2.2 软件构成

应用程序是用来完成生产工艺全部控制任务的,借助于莫迪康公司提供的强功能编程软件Modsoft和工程软件Modfix可开发出符合生产实际的自动控制程序。本系统软件设计的指导思想是:既要节省硬件投资,以软件代替硬件,又要提高软件的可靠性和运行速度。因此在编制程序时,将全厂设备按车间划分为多个子系统,便于顺序启停设备;而生产过程的监控则要面向整个选煤厂。根据这一原则,该软件包括以下三个主要部分: 2.2.1 集控启停设备程序

严格遵守逆煤流启动,顺煤流停止的闭锁关系。启动系统前,岗位人员首先在现场按钮箱上将“就地/禁止/集控”转换开关置于“集控”位,确认此台设备投入集控方式运行。在各种保护开关处于正常工作状态时,操作人员便可发出集中起车指令,于是PLC依次延时输出各台设备的启动指令,但发出的启动指令必须以上1台设备可靠启动为前提。2.2.2 生产过程监控程序

采取画面动态显示方式。在CRT上可以形象地观察到参与集控的每台设备的工作情况,主要有给料机、刮板机、皮带机的运转与否和溜槽翻板的位置,用黄色、蓝色、绿色分别表示设备处于就地、集控、运行三种状态。各储煤仓用棒形图表示,图形内部充填颜色,颜色不断变化的高度反映了仓中的实际料位。2.2.3 故障报警处理程序

每个子系统在集控启动过程中以及处于正常运行状态时,一旦有任意一台设备出现故障,该设备和上游设备必须全线停车,同时启动故障报警程序,使发生故障的设备在CRT画面上用不停闪动的红色醒目地显示,并将其设备号及故障发生时间打印输出。设备故障包括皮带跑偏、打滑、拉绳和溜槽堵塞以及岗位人员就地停止设备或重使转换开关处于非“集控”位等。应用效果

投入试生产以来,可编程序控制系统的性能日趋稳定,产品质量基本达到标准要求,但也暴露出一些实际问题:

首先,要实现计算机管理生产,软件维护人员不仅需要具备一定的计算机知识,能够修改和补充应用程序,以适应生产情况的变化,而且还应懂得继电控制理论。只有这样,才能真正发挥可编程序控制器的优势。因此,必须进一步加强高素质人员的培训。

其次,因溜槽翻板位置信号不稳定,常导致生产系统在集控方式下不能连续运行。由于翻板限位开关安装在电动推杆内部,在长时间经受煤流振动的情况下,触点虚接,造成信号丢失,而且微动开关损坏后更换困难。经过摸索,现采用电液推杆驱动翻板,并将限位开关固定在推杆外部,使其受振动小亦便于维护。改进后系统运行状况良好,性能稳定。结 语

可编程序控制器将计算机技术、通信技术和自动化技术融为一体,现已被广泛地应用于各种生产过程的自动控制中,文中介绍的集中控制系统,是一个较为成功的应用实例。

6.数控编程经验总结 篇六

开粗:在机床的最大负荷下,绝大部分情况应选用尽可能大的刀,尽可能大的的进刀量,尽可能快的进给。在同一把刀的情况下,进给与进刀量成反比。一般情况下,机床的负荷不是问题,选刀的原则主要依产品的二维角与三维弧是否过小来考虑。选好刀后,便定刀长,原则是刀长大于加工深度,大工件则要考虑夹头是否有干涉。光刀:光刀的目的是为了达到满足工件表面光洁度、预留适当余量的加工要求。同样,光刀选用尽可能大的刀,尽可能快的时间,因为精刀需要较长的时间,用最合适的进刀与进给。在同一进给下横向进刀越大越快,曲面进刀量与加工后的光洁度有关,进给的大小与曲面的外表形状有关,在不伤及面的情况下,留最小的余量、用最大的刀、最快的转速、适当的进给。

二、装夹方法:

1、所有的装夹都是横长竖短。

2、虎钳装夹:装夹高度不应低于10个毫米,在加工工件时必须指明装夹高度与加工高度。加工高度应高出虎钳平面5毫米左右,目的是保证牢固性,同时不伤及虎钳。此种装夹属一般性的装夹,装夹高度还与工件大小有关,工件越大,则装夹高度相应增大。

3、夹板装夹:夹板用码仔码在工作台上,工件用螺丝锁在夹板上,此种装夹适用于装夹高度不够及加工力较大的工件,一般中大型工件,效果比较好。

4、码铁装夹:在工件较大、装夹高度不够,又不准在底部锁缧丝时,则用码铁装夹。此种装夹需二次装夹,先码好四角,加工好其它部分,然后再码四边,加工四角。二次装夹时,不要让工件松动,先码再松。也可以先码两边,加工另两边。

5、刀具的装夹:直径10mm以上,装夹长度不低于30mm;直径10mm以下,装夹长度不低于20mm。刀具的装夹要牢固,严防撞刀与直接插入工件。

三、刀具的分类及其适用范围:

1、按材质分:

白钢刀:易磨损,用于铜公及小钢料开粗。钨钢刀:用于清角(特别是钢料)及光刀。合金刀:类似于钨钢刀。紫刀:用于高速切削,不易磨损。

2、按刀头分:

平底刀:用于平面及直身侧面,清平面角。球刀:用于各种曲面中光、光刀。

牛鼻刀(有单边、双边及五边):用于钢料开粗(R0.8、R0.3、R0.5、R0.4)。粗皮刀:用于开粗,注意余量的留法(0.3)。

3、按刀杆分:

直杆刀:直杆刀适用各种场合。

斜杆刀:但不适用于直身面及斜度小于杆斜度的面。

4、按刀刃分:

两刃、三刃、四刃,刃数越多,效果越好,但做功越多,转速及进给相应调整,刃数多寿命长。

5、球刀与飞刀光刀的区别:

球刀:凹面尺小于球尺,平面尺小于球R时,光不到(清不到底角)。

飞刀:优点是能清底角。相同参数的比较:V=R*ω转速快许多(飞刀),力大光出的东西亮,飞刀较多地用于等高外形,有时用飞刀不需中光。缺点是凹面尺寸及平面尺小于飞刀直径时光不到。

四、CNC配合电火花加工,铜公的做法:

1、什么情况下需要做铜公:

刀完全下不去要做铜公,在一个铜公中还有下不去的,形状是凸出需再分。刀能下去,但易断刀的也需做铜公,这需根据实际情况而定。要求火花纹的产品需做铜公。铜公做不成的,骨位太薄太高,易损公且易变形,加工中变形与打火花变形,此时需镶件。

铜公加工出的东西表面(特别是曲面会很顺很均匀)能克服精锣中的许多问题与绘图中的许多问题。要求精确外形或余量多时必须做粗铜公。

2、铜公的做法:

选出要做铜公的面,补全该补的面,或延长该延的面,保证铜公的所有边缘大于要打的边缘同时不伤及其它产品的面,去掉不必要的清不到的平面角(与平面角相交处是更深的胶位),补成规则形状;找出铜公最大外形,用一边界然后投影到托面;定出基准框大小,剪掉掉托面,到此铜公图基本完成;备料:长*宽*高,长与宽≥Ymax与Xmax为基准框实际铜料的长宽必须大于图上基准框。高≥铜公的理论尺寸+基准框高+装夹高度。

五、图纸定数问题:

1、在没有现成的加工面下,平面四面分中,中心对原点,顶面对零,顶面不平时(铜公而言)留0.1的余量,即碰数时,实际对(z),图上偏低0.1。

2、当有现成的加工面时,使图上的现成面对0(z),平面能分中则分中,否则以现成边碰数(单边)加工面则要校核实际高度,宽,长与图纸差别,按实际的料来编程。一般情况,先加工成图上的尺寸再加工图上形状。

3、当要多个位加工时,第一个位(标准位),就要把其它几个位的基准锣好,长宽高都要锣,所有下一次加工基准要以上次已加工好的面为准。

4、镶件的定位:放在整体里面,把下面垫起一定高度然后图纸也升高此高度,平面按整体分中,高度按图下面用镙丝锁住;是方方正正的则可直分中;粗略一点可用最大外形分中;割一夹具,按夹具分中,镶件图与夹具的相对位置确定然后把图纸原点放在夹具中心点。

六、开粗的刀路选择:

1、曲面挖槽:

关键是范围的选择与面的选择,刀路加工的区域是以所选范围内所选面为终止面,从最高点到最低点刀具能下得去的所有地方为原则。所选面最好是全体面,边界则只能是所要加工的区域,无面处延伸小于半个刀径的距离,因为其它面留有足够余量所以自动保护;最好延伸最低线,因为最低处有一个R锣不到。

刀的选择:如刀具不能螺旋或斜线进刀时或加工不到的区域进不了刀的区域封起,留待二次开粗。光刀之前,一定要把未开粗的区域全部开粗,特别是小角,其中包括二维角,三维角及封起来的区域,不然则会断刀。

二次开粗:一般用三维挖槽选范围,平底刀,能用平面挖槽与外形刀路的则用。在不伤及其它面的情况下刀具中心到所选边界,一般不精修边界,用快速双向角度视情况而定,螺旋进刀,角度1.5度,高1,当挖槽形状为条形,不能螺旋下刀则用斜线进刀,一般打开过滤,特别是曲面开粗,进刀平面不可低,以免撞刀,安全高度不可低。

退刀:一般不用相对退刀,用绝对退刀,当没有岛屿时则用相对退刀。

2、平面挖槽:铣各种平面,凹平槽,当铣部分开放式平面时,则需定边界,原则能进刀(大于一个刀径),开放处偏外大于半个刀径,封闭外围。

3、外形:当所选平面适合外形分层,则用外形分层提刀(平面外形),提刀点与下刀点为一点时,不须提刀z平面一般提刀,尽量不用相对高度;补正方向一般右补正(顺刀)。

4、机械补正的刀路设置:补正号为21,改电脑补正机械补正,进刀为垂直进刀,刀过不了的地方则改大R不留余量。

5、等高外形:适合于走封闭式的面,走开放式的面若是四圈则要封项面,若是四圈内或非四圈则要选范围与高度(一定弧形进刀开粗),用于开粗的情况:任一平面内的加工距离小于一个刀径,若大于一个刀径则要用更大的刀或两次等高外形。

6、曲面流线:具有最好的均匀性与干脆性,适合光刀很多时候可取代等高外形。

7、放射刀路:适合中间有大孔的情况(少用)。注意事项:弹刀,刀不锋利,刀过长,工件过深时要环绕走不可上下走;工件中的利角两边的面要分两个刀路,不可越过去,光刀时的边缘最好延长(用弧线进退刀)。

七、清角:

1、这里的清角清的是二维死角,是前面工序都未曾走到的部分,如光刀需走到的地方则应先清角再光刀,太小大深的角可分几把刀清,不要用小刀清太多地方。

2、清三维角:开一些小槽,一些三维转角处。

3、易断刀,一定要考虑像细刀、过长,加工量过大(主要是z向,深度方向)的情况。

4、刀路:用二维外形走,只能清小角(R0.8)及二维平面角;用平行刀路;用等高外形;有一种地方刀子去不了的曲面及外形走不到的死角则要先封起来起刀,最后清角,大面中的小缺口一般先封起来。

八、中光:

1、中光:作为曲面的钢料与细公才中光。

2、原则:大刀开粗时层与层间的余量较多,为使光刀时得到更好效果的一道工序,3、特点:快速清除,大刀飞刀亦可,大进给,大间距;不必顾忌表面质量;平面的工件不必中光;等高外形的工件不用中光,等高外形开粗时可细一点把两道工序放在一起,细一点指表面余量与层与层的距离;需不需中光,还有一个重要因素是工作的材料,材料越硬,则考虑中光;中光的加工方向与光刀开粗最好相对这样加工的东西会效果好,均匀。

九、光刀:

光刀是要达到各种产品与模具的装配要求所以要非常慎重,根据不同的要求给予不同的刀路设置与参数设置。

1、光刀的下刀高度与最后高度都改为0,公差设计1个丝以内,不需过滤(工件越小公差越小,公差影响外型)。

2、前模与分型面要达到最好的光洁度,后模可次,其它非配合及避空位可粗糙点。

3、刀路设计由以下因素决定:

具体外形(如平面与其它面),陡峭面与平坦曲面。两面之间是否利角(利角则分开)。两部分是否要求不同(要不要留余量,余量的多少,光洁度的要求不同)。光刀中保护面问题是个大问题,对已加工好的面一定要预到加工中的误差保护起来,按保护面的要求保护起来。范围保护,不计误差的0保护,高度范围与平面范围;保护面保护。

刀路的延长问题:光刀中,刀路加工到边缘时最好作圆弧进退刀否则事先把面稍加延长。

光刀中的提刀问题:提刀浪费时间,所以尽量避免提刀。方法1:设提刀间隙(小缺口)

方法2:封面,把提刀处封起来(小缺口)方法3:避开间隙(大缺口处)

7.多线程编程知识总结 篇七

一、问题的提出

1.1问题的引出

编写一个耗时的单线程程序:

新建一个基于对话框的应用程序SingleThread,在主对话框IDD_SINGLETHREAD_DIALOG添加一个按钮,ID为IDC_SLEEP_SIX_SECOND,标题为“延时6秒”,添加按钮的响应函数,代码如下:

void CSingleThreadDlg::OnSleepSixSecond(){ Sleep(6000);//延时6秒 } 编译并运行应用程序,单击“延时6秒”按钮,你就会发现在这6秒期间程序就象“死机”一样,不在响应其它消息。为了更好地处理这种耗时的操作,我们有必要学习——多线程编程。

1.2多线程概述

进程和线程都是操作系统的概念。进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭。

线程是进程内部的一个执行单元。系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说main或WinMain函数,将程序的启动点提供给Windows系统。主执行线程终止了,进程也就随之终止。

每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的。用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中。一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛。

多线程可以实现并行处理,避免了某项任务长时间占用CPU时间。要说明的一点是,对于单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行。由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能。这一点在多线程编程时应该注意。

Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作。Visual C++中,使用MFC类库也实现了多线程的程序设计,使得多线程编程更加方便。1.3 Win32 API对多线程编程的支持

Win32 提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作。下面将选取其中的一些重要函数进行说明。

1、HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:

lpThreadAttributes:指向一个 SECURITY_ATTRIBUTES 结构的指针,该结构决定了线程的安全属性,一般置为 NULL;

dwStackSize:指定了线程的堆栈深度,一般都设置为0;

lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc 是线程函数名;

lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;

dwCreationFlags:控制线程创建的附加标志,可以取两种值。如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;

lpThreadId:该参数返回所创建线程的ID;

如果创建成功则返回线程的句柄,否则返回NULL。

2、DWORD SuspendThread(HANDLE hThread);该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止。

3、DWORD ResumeThread(HANDLE hThread);该函数用于结束线程的挂起状态,执行线程。

4、VOID ExitThread(DWORD dwExitCode);该函数用于线程终结自身的执行,主要在线程的执行函数中被调用。其中参数dwExitCode用来设置线程的退出码。

5、BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);

一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用TerminateThread强行终止某一线程的执行。各参数含义如下: hThread:将被终结的线程的句柄;

dwExitCode:用于指定线程的退出码。

使用TerminateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源。因此,一般不建议使用该函数。

6、BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam,LPARAM lParam);该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回。idThread:将接收消息的线程的ID;

Msg:指定用来发送的消息;

wParam:同消息有关的字参数;

lParam:同消息有关的长参数;

调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败。

1.4.Win32 API多线程编程例程

例程1 [MultiThread1] 一个简单的线程。注意事项:

 Volatile:关键字:

volatile是要求C++编译器不要自作聪明的把变量缓冲在寄存器里.因为该变量可能会被意外的修改。(多个线程或其他原因)

如从串口读数据的场合,把变量缓冲在寄存器里,下次去读寄存器就没有意义了.因为串口的数据可能随时会改变的.加锁访问用于多个线程的场合.在进入临界区时是肯定要加锁的.volatile也加上,以保证从内存中读取变量的值. 终止线程:

Windows终止线程运行的四种方法 终止线程运行

若要终止线程的运行,可以使用下面的方法:

• 线程函数返回(最好使用这种方法)。

• 通过调用 ExitThread 函数,线程将自行撤消(最好不要使用这种方法)。

• 同一个进程或另一个进程中的线程调用 TerminateThread 函数(应该避免使用这种方法)。

• 包含线程的进程终止运行(应该避免使用这种方法)。

下面将介绍终止线程运行的方法,并且说明线程终止运行时会出现什么情况。

 线程函数返回

始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。

如果线程能够返回,就可以确保下列事项的实现:

• 在线程函数中创建的所有 C++ 对象均将通过它们的撤消函数正确地撤消。

• 操作系统将正确地释放线程堆栈使用的内存。

• 系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。

• 系统将递减线程内核对象的使用计数。 使用 ExitThread 函数

可以让线程调用 ExitThread 函数,以便强制线程终止运行:

VOID ExitThread(DWORD dwExitCode);

该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++ 资源(如 C++ 类对象)将不被撤消。由于这个原因,最好从线程函数返回,而不是通过调用 ExitThread 来返回。

当然,可以使用 ExitThread 的 dwExitThread 参数告诉系统将线程的退出代码设置为什么。ExitThread 函数并不返回任何值,因为线程已经终止运行,不能执行更多的代码。 使用 TerminateThread 函数

调用 TerminateThread 函数也能够终止线程的运行:

BOOL TerminateThread(HANDLE hThread, DWORD dwExitCode);

与 ExitThread 不同,ExitThread 总是撤消调用的线程,而 TerminateThread 能够撤消任何线程。hThread 参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为 dwExitCode 参数传递的值。同时,线程的内核对象的使用计数也被递减。

注意 TerminateThread 函数是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,当函数返回时,不能保证线程被撤消。如果需要确切地知道该线程已经终止运行,必须调用 WaitForSingleObject 或者类似的函数,传递线程的句柄。

设计良好的应用程序从来不使用这个函数,因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。

注意 当使用返回或调用 ExitThread 的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用 TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。Microsoft故意用这种方法来实现 TerminateThread。如果其他仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其他的线程就会出现访问违规的问题。如果将已经撤消的线程的堆栈留在内存中,那么其他线程就可以继续很好地运行。

此外,当线程终止运行时,DLL 通常接收通知。如果使用 TerminateThread 强迫线程终止,DLL 就不接收通知,这能阻止适当的清除,在进程终止运行时撤消线程。当线程终止运行时,会发生下列操作:

• 线程拥有的所有用户对象均被释放。在 Windows 中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。

• 线程的退出代码从 STILL_ACTIVE 改为传递给 ExitThread 或 TerminateThread 的代码。

• 线程内核对象的状态变为已通知。

• 如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。

• 线程内核对象的使用计数递减 1。

当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。

一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用 GetExitcodeThread 来检查由 hThread 标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码:

BOOL GetExitCodeThread(HANDLE hThread, PDOWRD pdwExitCode);退出代码的值在 pdwExitCode 指向的 DWORD 中返回。如果调用 GetExitCodeThread 时线程尚未终止运行,该函数就用 STILL_ACTIVE 标识符(定义为 0x103)填入 DWORD。如果该函数运行成功,便返回 TRUE。

 线程的定义:

例程2[MultiThread2] 传送一个一个整型的参数到一个线程中,以及如何等待一个线程完成处理。

DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);

hHandle:为要监视的对象(一般为同步对象,也可以是线程)的句柄;

dwMilliseconds:为hHandle对象所设置的超时值,单位为毫秒;

当在某一线程中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态。如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

例程3[MultiThread3] 传送一个结构体给一个线程函数,可以通过传送一个指向结构体的指针参数来完成。补充一点:如果你在void CMultiThread3Dlg::OnStart()函数中添加/* */语句,编译运行你就会发现进度条不进行刷新,主线程也停止了反应。什么原因呢?这是因为WaitForSingleObject函数等待子线程(ThreadFunc)结束时,导致了线程死锁。因为WaitForSingleObject函数会将主线程挂起(任何消息都得不到处理),而子线程ThreadFunc正在设置进度条,一直在等待主线程将刷新消息处理完毕返回才会检测通知事件。这样两个线程都在互相等待,死锁发生了,编程时应注意避免。

例程4[MultiThread4] 测试在Windows下最多可创建线程的数目。

二、MFC中的多线程开发

2.1 MFC对多线程编程的支持

MFC中有两类线程,分别称之为工作者线程和用户界面线程。二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环。

工作者线程没有消息机制,通常用来执行后台计算和维护任务,如冗长的计算过程,打印机的后台打印等。用户界面线程一般用于处理独立于其他线程执行之外的用户输入,响应用户及系统所产生的事件和消息等。但对于Win32的API编程而言,这两种线程是没有区别的,它们都只需线程的启动地址即可启动线程来执行任务。

在MFC中,一般用全局函数AfxBeginThread()来创建并初始化一个线程的运行,该函数有两种重载形式,分别用于创建工作者线程和用户界面线程。两种重载函数原型和参数分别说明如下:

(1)CWinThread* AfxBeginThread(AFX_THREADPROC pfnThreadProc,LPVOID pParam,nPriority=THREAD_PRIORITY_NORMAL,UINT nStackSize=0,DWORD dwCreateFlags=0,LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);

PfnThreadProc:指向工作者线程的执行函数的指针,线程函数原型必须声明如下: UINT ExecutingFunction(LPVOID pParam);请注意,ExecutingFunction()应返回一个UINT类型的值,用以指明该函数结束的原因。一般情况下,返回0表明执行成功。

pParam:传递给线程函数的一个32位参数,执行函数将用某种方式解释该值。它可以是数值,或是指向一个结构的指针,甚至可以被忽略;

nPriority:线程的优先级。如果为0,则线程与其父线程具有相同的优先级;

nStackSize:线程为自己分配堆栈的大小,其单位为字节。如果nStackSize被设为0,则线程的堆栈被设置成与父线程堆栈相同大小; dwCreateFlags:如果为0,则线程在创建后立刻开始执行。如果为CREATE_SUSPEND,则线程在创建后立刻被挂起;

lpSecurityAttrs:线程的安全属性指针,一般为NULL;

(2)CWinThread* AfxBeginThread(CRuntimeClass* pThreadClass,int nPriority=THREAD_PRIORITY_NORMAL,UINT nStackSize=0,DWORD dwCreateFlags=0,LPSECURITY_ATTRIBUTES lpSecurityAttrs=NULL);

pThreadClass 是指向 CWinThread 的一个导出类的运行时类对象的指针,该导出类定义了被创建的用户界面线程的启动、退出等;其它参数的意义同形式1。使用函数的这个原型生成的线程也有消息机制,在以后的例子中我们将发现同主线程的机制几乎一样。下面对CWinThread类的数据成员及常用函数进行简要说明。

   m_hThread:当前线程的句柄;

m_nThreadID:当前线程的ID;

m_pMainWnd:指向应用程序主窗口的指针

virtual BOOL CWinThread::InitInstance();重载该函数以控制用户界面线程实例的初始化。初始化成功则返回非0值,否则返回0。用户界面线程经常重载该函数,工作者线程一般不使用InitInstance()。

virtual int CWinThread::ExitInstance();在线程终结前重载该函数进行一些必要的清理工作。该函数返回线程的退出码,0表示执行成功,非0值用来标识各种错误。同InitInstance()成员函数一样,该函数也只适用于用户界面线程。

2.2 MFC多线程编程实例

例程5 MultiThread5 为了与Win32 API对照,使用MFC 类库编程实现例程3 MultiThread3。

例程6 MultiThread6[用户界面线程]  创建用户界面线程的步骤:

1.使用ClassWizard创建类CWinThread的派生类(以CUIThread类为例)class CUIThread : public CWinThread { DECLARE_DYNCREATE(CUIThread)protected: CUIThread();// protected constructor used by dynamic creation

// Attributes public: // Operations public:

// Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CUIThread)public: virtual BOOL InitInstance();virtual int ExitInstance();//}}AFX_VIRTUAL // Implementation protected: virtual ~CUIThread();// Generated message map functions //{{AFX_MSG(CUIThread)

// NOTE-the ClassWizard will add and remove member functions here.//}}AFX_MSG

DECLARE_MESSAGE_MAP()};

2.重载函数InitInstance()和ExitInstance()。BOOL CUIThread::InitInstance(){ CFrameWnd* wnd=new CFrameWnd;wnd->Create(NULL,“UI Thread Window”);wnd->ShowWindow(SW_SHOW);wnd->UpdateWindow();m_pMainWnd=wnd;return TRUE;}

3.创建新的用户界面线程 void CUIThreadDlg::OnButton1(){

}

请注意以下两点:

A、在UIThreadDlg.cpp的开头加入语句: #include “UIThread.h” B、把UIThread.h中类CUIThread()的构造函数的特性由 protected 改为 public。CUIThread* pThread=new CUIThread();pThread->CreateThread();

用户界面线程的执行次序与应用程序主线程相同,首先调用用户界面线程类的InitInstance()函数,如果返回TRUE,继续调用线程的Run()函数,该函数的作用是运行一个标准的消息循环,并且当收到WM_QUIT消息后中断,在消息循环过程中,Run()函数检测到线程空闲时(没有消息),也将调用OnIdle()函数,最后Run()函数返回,MFC调用ExitInstance()函数清理资源。

你可以创建一个没有界面而有消息循环的线程,例如:你可以从CWinThread派生一个新类,在InitInstance函数中完成某项任务并返回FALSE,这表示仅执行InitInstance函数中的任务而不执行消息循环,你可以通过这种方法,完成一个工作者线程的功能。

三、线程间通讯

3.1通讯方式

一般而言,应用程序中的一个次要线程总是为主线程执行特定的任务,这样,主线程和次要线程间必定有一个信息传递的渠道,也就是主线程和次要线程间要进行通信。这种线程间的通信不但是难以避免的,而且在多线程编程中也是复杂和频繁的,下面将进行说明。

3.1.1使用全局变量进行通信

由于属于同一个进程的各个线程共享操作系统分配该进程的资源,故解决线程间通信最简单的一种方法是使用全局变量。对于标准类型的全局变量,建议使用volatile 修饰符,它告诉编译器无需对该变量作任何的优化,即无需将它放到一个寄存器中,并且该值可被外部改变。如果线程间所需传递的信息较复杂,可以定义一个结构,通过传递指向该结构的指针进行传递信息。

3.1.2使用自定义消息

可以在一个线程的执行函数中向另一个线程发送自定义的消息来达到通信的目的。一个线程向另外一个线程发送消息是通过操作系统实现的。利用Windows操作系统的消息驱动机制,当一个线程发出一条消息时,操作系统首先接收到该消息,然后把该消息转发给目标线程,接收消息的线程必须已经建立了消息循环。

3.2例程

例程GlobalObjectTest 该例程演示了如何利用全局变量进行通信

例程7[MultiThread7] 该例程演示了如何使用自定义消息进行线程间通信。首先,主线程向CCalculateThread线程发送消息WM_CALCULATE,CCalculateThread线程收到消息后进行计算,再向主线程发送WM_DISPLAY消息,主线程收到该消息后显示计算结果。步骤:

四、线程的同步

4.1基本概念

虽然多线程能给我们带来好处,但是也有不少问题需要解决。例如,对于像磁盘驱动器这样独占性系统资源,由于线程可以执行进程的任何代码段,且线程的运行是由系统调度自动完成的,具有一定的不确定性,因此就有可能出现两个线程同时对磁盘驱动器进行操作,从而出现操作错误;又例如,对于银行系统的计算机来说,可能使用一个线程来更新其用户数据库,而用另外一个线程来读取数据库以响应储户的需要,极有可能读数据库的线程读取的是未完全更新的数据库,因为可能在读的时候只有一部分数据被更新过。

使隶属于同一进程的各线程协调一致地工作称为线程的同步。MFC提供了多种同步对象,下面只介绍最常用的四种:

临界区(CCriticalSection)

事件(CEvent)

互斥量(CMutex)

信号量(CSemaphore)

通过这些类,可以比较容易地做到线程同步。

4.2使用 CCriticalSection 类

当多个线程访问一个独占性共享资源时,可以使用“临界区”对象。任一时刻只有一个线程可以拥有临界区对象,拥有临界区的线程可以访问被保护起来的资源或代码段,其他希望进入临界区的线程将被挂起等待,直到拥有临界区的线程放弃临界区时为止,这样就保证了不会在同一时刻出现多个线程访问共享资源。

CCriticalSection类的用法非常简单,步骤如下:

1.定义CCriticalSection类的一个全局对象(以使各个线程均能访问),如CCriticalSection critical_section;

2.在访问需要保护的资源或代码之前,调用CCriticalSection类的成员Lock()获得临界区对象: critical_section.Lock();3.在线程中调用该函数来使线程获得它所请求的临界区。如果此时没有其它线程占有临界区对象,则调用Lock()的线程获得临界区;否则,线程将被挂起,并放入到一个系统队列中等待,直到当前拥有临界区的线程释放了临界区时为止。

4.访问临界区完毕后,使用CCriticalSection的成员函数Unlock()来释放临界区:critical_section.Unlock();通俗讲,就是线程A执行到critical_section.Lock();语句时,如果其它线程(B)正在执行critical_section.Lock();语句后且critical_section.Unlock();语句前的语句时,线程A就会等待,直到线程B执行完critical_section.Unlock();语句,线程A才会继续执行。

例程8 MultiThread8 4.3使用 CEvent 类

CEvent 类提供了对事件的支持。事件是一个允许一个线程在某种情况发生时,唤醒另外一个线程的同步对象。例如在某些网络应用程序中,一个线程(记为A)负责监听通讯端口,另外一个线程(记为B)负责更新用户数据。通过使用CEvent 类,线程A可以通知线程B何时更新用户数据。每一个CEvent 对象可以有两种状态:有信号状态和无信号状态。线程监视位于其中的CEvent 类对象的状态,并在相应的时候采取相应的操作。

在MFC中,CEvent 类对象有两种类型:人工事件和自动事件。一个自动CEvent 对象在被至少一个线程释放后会自动返回到无信号状态;而人工事件对象获得信号后,释放可利用线程,但直到调用成员函数ReSetEvent()才将其设置为无信号状态。在创建CEvent 类的对象时,默认创建的是自动事件。CEvent 类的各成员函数的原型和参数说明如下:

1、CEvent(BOOL bInitiallyOwn=FALSE,BOOL bManualReset=FALSE,LPCTSTR lpszName=NULL,LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);bInitiallyOwn:指定事件对象初始化状态,TRUE为有信号,FALSE为无信号;

bManualReset:指定要创建的事件是属于人工事件还是自动事件。TRUE为人工事件,FALSE为自动事件;

后两个参数一般设为NULL,在此不作过多说明。

2、BOOL CEvent::SetEvent();

将 CEvent 类对象的状态设置为有信号状态。如果事件是人工事件,则 CEvent 类对象保持为有信号状态,直到调用成员函数ResetEvent()将 其重新设为无信号状态时为止。如果CEvent 类对象为自动事件,则在SetEvent()将事件设置为有信号状态后,CEvent 类对象由系统自动重置为无信号状态。

如果该函数执行成功,则返回非零值,否则返回零。

3、BOOL CEvent::ResetEvent();

该函数将事件的状态设置为无信号状态,并保持该状态直至SetEvent()被调用时为止。由于自动事件是由系统自动重置,故自动事件不需要调用该函数。如果该函数执行成功,返回非零值,否则返回零。一般通过调用WaitForSingleObject函数来监视事件状态。前面已经介绍了该函数。由于语言描述的原因,CEvent 类的理解确实有些难度,只要通过下面例程,多看几遍就可理解。例程9 MultiThread9 仔细分析这两个线程函数, 就会正确理解CEvent 类。线程WriteD执行到 WaitForSingleObject(eventWriteD.m_hObject,INFINITE);处等待,直到事件eventWriteD为有信号该线程才往下执行,因为eventWriteD对象是自动事件,则当WaitForSingleObject()返回时,系统自动把eventWriteD对象重置为无信号状态。

4.4使用CMutex 类

互斥对象与临界区对象很像.互斥对象与临界区对象的不同在于:互斥对象可以在进程间使用,而临界区对象只能在同一进程的各线程间使用。当然,互斥对象也可以用于同一进程的各个线程间,但是在这种情况下,使用临界区会更节省系统资源,更有效率。

4.5使用CSemaphore 类

当需要一个计数器来限制可以使用某个线程的数目时,可以使用“信号量”对象。CSemaphore 类的对象保存了对当前访问某一指定资源的线程的计数值,该计数值是当前还可以使用该资源的线程的数目。如果这个计数达到了零,则所有对这个CSemaphore 类对象所控制的资源的访问尝试都被放入到一个队列中等待,直到超时或计数值不为零时为止。一个线程被释放已访问了被保护的资源时,计数值减1;一个线程完成了对被控共享资源的访问时,计数值增1。这个被CSemaphore 类对象所控制的资源可以同时接受访问的最大线程数在该对象的构建函数中指定。

CSemaphore 类的构造函数原型及参数说明如下:

CSemaphore(LONG lInitialCount=1,LONG lMaxCount=1,LPCTSTR pstrName=NULL,LPSECURITY_ATTRIBUTES lpsaAttributes=NULL);lInitialCount:信号量对象的初始计数值,即可访问线程数目的初始值;

lMaxCount:信号量对象计数值的最大值,该参数决定了同一时刻可访问由信号量保护的资源的线程最大数目;

后两个参数在同一进程中使用一般为NULL,不作过多讨论;

在用CSemaphore 类的构造函数创建信号量对象时要同时指出允许的最大资源计数和当前可用资源计数。一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就可以发出信号量信号。但是当前可用计数减小到0时,则说明当前占用资源的线程数已经达到了所允许的最大数目,不能再允许其它线程的进入,此时的信号量信号将无法发出。线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可用资源数加1。例程10 MultiThread10 为了文件中能够正确使用同步类,在文件开头添加: #include “afxmt.h” 定义信号量对象和一个字符数组,为了能够在不同线程间使用,定义为全局变量:CSemaphore semaphoreWrite(2,2);//资源最多访问线程2个,当前可访问线程数2个

8.软件编程实习总结_工作总结 篇八

实习时间:3月1日———5月9日 实习地点:广州xx大学生实训基地 实训目标:

1.通过系统性的实训,熟练掌握java se、java ee知识体系,具备java开发经验;

2.了解企业软件开发流程规范,初步具备正确的软件开发编程思路,掌握软件开发的基本方法,养成规范化项目开发习惯; 3.以项目案例带动实训,以企业开发为基础,对参加实训学生进行项目分组管理,学生需按要求完成每天布置的项目案例,实训结束时必须按要求完成多个项目开发工作,通过案例练习、企业项目开发、评审,使学生初步具备软件开发的实战能力; 实习单位概述:xx科技以中关村科技园区为依托,在中国软件业发达城市——北京、上海、广州、深圳、大连、南京、武汉、杭州、西安、苏州、成都、太原等20大城市,建立了近40家培训中心,占地2万平米,年培训1万多名软件人才。已累计为ibm、微软、摩托罗拉、华为、中软、用友、yahoo、阿里巴巴、tom、新浪、搜狐、百度、联想、神州数码、大唐电信、亚信等知名it企业培养输送了7万多名中高级软件人才,目前xx全国拥有600多名员工,年产值近2亿元,是中国领先的中高端软件人才培训机构。xx科技目前提供的职业培训包括:外企软件开发工程师、软件测试工程师、oracle数据库管理员、unix系统

管理员、网络系统工程师。实习概况:

1.java语言简介。包括java的发展、java语言的特点、java应用程序的运行机制和环境、java的垃圾回收机制、java开发环境的安装和配置和java源程序的编译和运行等。

其中,配置java开发环境时,需要修改环境变量(先在系统变量中新建一个java_home的变量,将其值设置为jdk1.6.0的安装路径;然后修改path变量,在该变量值类加入路:%java_home%bin;%java_home%jrebin;接着再修改classpath变量,若没有手动加入,在其值类加入路径:.;最后利用javac-version测试java的版本);在编译和运行java源程序时,先使用javac *.java进行编译,再利用java *进行运行。

2.java基本语法。包括java的命名规范、注释、标识符、数据类型、变量、运算符、表达式、控制语句等。其中,java的命名规范包括:以字母(unicode)﹑“$”﹑“—”﹑为开头。第二个字符开始是字母(unicode)、数字、“$”﹑“—”,不限制长度,不能是 java的关键字,区分大小写和可以是中文;java的基本数据类型有八种:整型类型(byte,short,int,long)、浮点类型(float,double)、字符型(char)和布尔型(boolean);java的控制语句包括:选择语句(if-else,switch-case)、循环语句(for,do-while,while)和循环跳转语句(break结束整个

循,continue结束本次循环)。

3.mysql数据库基本指令。包括创建、查询、删除数据库和表,向表中添加、删除、更新数据和查询表,修改表的结构等。其中,列出数据库实例和表: show databases; show tables; 使用数据库实例: use databasename; 显示表中列的属性: desc tablename; 创建一张表:

create table tablename(属性及其数据类型); 查询数据:

select * from tablename(where id=); 添加数据:

insert into tablename(属性1,...)values(属性值1,...);删除数据:

delete from tablename(where id=); 更新数据:

update tablename set 字段名=„„,字段名

=„„(where id=); 表结构的修改,如增加一个字段格式:

alter table tablename add column(字段名,字段类型); 4.数组的介绍。包括数组的申明,初始化(静态和动态初始化),数组的访问、遍历和复制等。

5.string中一些api方法。如找到指定位置的字符charat(int index),求字符串的长度length(),字符串的连接concat、判断字符串是否以指定的字符结束engswith(‘c’)、判断两个字符串是否相等equal等。

6.接口的介绍。包括collection、list、hashmap等,以及这些接口的一些api的使用。7.类的封装和重载。

9.学习面向切面编程的总结 篇九

AOP(面向切面编程)

可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于

各个模块的重用。

而AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。

使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。

北大青鸟中关村

比如权限认证、日志、事务处理。Aop的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”

实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。然而殊途同归,实现AOP的技术特性却是相同的,分别为:

1、join point(连接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。

2、point cut(切入点):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。

3、advice(通知):是point cut的执行代码,是执行“方面”的具体逻辑。

4、aspect(方面):point cut和advice结合起来就是aspect,它类似于OOP中定义的一个类,但它代表的更多是对象间横向的关系。

5、introduce(引入):为对象引入附加的方法或属性,从而达到修改对象结构的目的。有的AOP工具又将其称为mixin。

上述的技术特性组成了基本的AOP技术,大多数AOP工具均实现了这些技术。它们也可以是研究AOP技术的基本术语。2.2.2 横切技术

北大青鸟中关村

“横切”是AOP的专有名词。它是一种蕴含强大力量的相对简单的设计和编程技术,尤其是用于建立松散耦合的、可扩展的企业系统时。横切技术可以使得AOP在一个给定的编程模型中穿越既定的职责部分(比如日志记录和性能优化)的操作。

如果不使用横切技术,软件开发是怎样的情形呢?在传统的程序中,由于横切行为的实现是分散的,开发人员很难对这些行为进行逻辑上的实现或更改。例如,用于日志记录的代码和主要用于其它职责的代码缠绕在一起。根据所解决的问题的复杂程度和作用域的不同,所引起的混乱可大可小。更改一个应用程序的日志记录策略可能涉及数百次编辑——即使可行,这也是个令人头疼的任务。

在AOP中,我们将这些具有公共逻辑的,与其他模块的核心逻辑纠缠在一起的行为称为“横切关注点(Crosscutting Concern)”,因为它跨越了给定编程模型中的典型职责界限。2.2.2.1 横切关注点

一个关注点(concern)就是一个特定的目的,一块我们感兴趣的区域,一段我们需要的逻辑行为。从技术的角度来说,一个典型的软件系统包含一些核心的关注点和系统级的关注点。举个例子来说,一个信用卡处理系统的核心关注点是借贷/存入处理,而系统级的关注点则是日志、事务完整性、授权、安全及性能问题等,许多关注点——即横切关注点(crosscutting concerns)——会在多个模块中出现。如果使用现有的编程方法,横切关注点会横越多个模块,结果是使系统难以设计、理解、实现和演进。AOP能够比上述方法更好地分离系统关注点,从而提供模块化的横切关注点。

北大青鸟中关村

例如一个复杂的系统,它由许多关注点组合实现,如业务逻辑、性能,数据存储、日志和调度信息、授权、安全、线程、错误检查等,还有开发过程中的关注点,如易懂、易维护、易追查、易扩展等,图2.1演示了由不同模块实现的一批关注点组成一个系统。

图2.1 把模块作为一批关注点来实现

通过对系统需求和实现的识别,我们可以将模块中的这些关注点分为:核心关注点和横切关注点。对于核心关注点而言,通常来说,实现这些关注点的模块是相互独立的,他们分别完成了系统需要的商业逻辑,这些逻辑与具体的业务需求有关。而对于日志、安全、持久化等关注点而言,他们却是商业逻辑模块所共同需要的,这些逻辑分布于核心关注点的各处。在AOP中,诸如这些模块,都称为横切关注点。应用AOP的横切技术,关键就是要实现对关注点的识别。

北大青鸟中关村

如果将整个模块比喻为一个圆柱体,那么关注点识别过程可以用三棱镜法则来形容,穿越三棱镜的光束(指需求),照射到圆柱体各处,获得不同颜色的光束,最后识别出不同的关注点。如图2.2所示:

图2.2 关注点识别:三棱镜法则

上图识别出来的关注点中,Business Logic属于核心关注点,它会调用到Security,Logging,Persistence等横切关注点。public class BusinessLogic { public void SomeOperation(){ //验证安全性;Securtity关注点;

//执行前记录日志;Logging关注点;

DoSomething();//保存逻辑运算后的数据;Persistence关注点;

//执行结束记录日志;Logging关注点;

} }

北大青鸟中关村

AOP的目的,就是要将诸如Logging之类的横切关注点从BusinessLogic类中分离出来。利用AOP技术,可以对相关的横切关注点封装,形成单独的“aspect”。这就保证了横切关注点的复用。由于BusinessLogic类中不再包含横切关注点的逻辑代码,为达到调用横切关注点的目的,可以利用横切技术,截取BusinessLogic类中相关方法的消息,例如SomeOperation()方法,然后将这些“aspect”织入到该方法中。例如图2.3:

图2.3 将横切关注点织入到核心关注点中

通过利用AOP技术,改变了整个系统的设计方式。在分析系统需求之初,利用AOP的思想,分离出核心关注点和横切关注点。在实现了诸如日志、事务管理、权限控制等横切关注点的通用逻辑后,开发人员就可以专注于核心关注点,将精力投入到解决企业的商业逻辑上来。同时,这些封装好了的横切关注点提供的功能,可以最大限度地复用于商业逻辑的各个部分,既不需要开发人员作特殊的编码,也不会因为修改横切关注点的功能而影响具体的业务功能。为了建立松散耦合的、可扩展的企业系统,AOP应用到的横切技术,通常分为两种类型:动态横切和静态横切。2.2.2.2 动态横切

北大青鸟中关村

动态横切是通过切入点和连接点在一个方面中创建行为的过程,连接点可以在执行时横向地应用于现有对象。动态横切通常用于帮助向对象层次中的各种方法添加日志记录或身份认证。在很多应用场景中,动态横切技术基本上代表了AOP。

动态横切技术的核心主要包括join point(连接点),point cut(切入点),advice(通知)和aspect(方面)。在前面,我已经概要地介绍了这些术语分别代表的含义。接下来,我将以一个具体的实例来进一步阐述它们在AOP动态横切中实现的意义。

考虑一个电子商务系统,需要对订单进行添加、删除等管理操作。毫无疑问,在实际的应用场景中,这些行为应与权限管理结合,只有获得授权的用户方能够实施这些行为。采用传统的设计方法,其伪代码如下: public class OrderManager { private ArrayListm_Orders;public OrderManager(){ m_Orders = new ArrayList();} public void AddOrder(Order order){ if(permissions.Verify(Permission.ADMIN)){

北大青鸟中关村

m_Orders.Add(order);} } public void RemoveOrder(Order order){ if(permissions.Verify(Permission.ADMIN)){ m_Orders.Remove(order);} } } 同样的,在该电子商务系统中,还需要对商品进行管理,它采用了同样的授权机制:

public class ProductManager { private ArrayListm_Products;public ProductManager(){ m_Products = new ArrayList();} public void AddProduct(Product product){ if(permissions.Verify(Permission.ADMIN))

北大青鸟中关村

{ m_Products.Add(product);} } public void RemoveProduct(Product product){ if(permissions.Verify(Permission.ADMIN)){ m_Products.Remove(product);} } } 如此以来,在整个电子商务系统中,核心业务包括订单管理和商品管理,它们都需要相同的权限管理,如图2.4所示:

图2.4 电子商务系统的权限验证实现

毫无疑问,利用AOP技术,我们可以分离出系统的核心关注点和横切关注点,从横向的角度,截取业务管理行为的内部消息,以达到织入权限管理逻辑的目

北大青鸟中关村 的。当执行AddOrder()等方法时,系统将验证用户的权限,调用横切关注点逻辑,因此该方法即为AOP的join point。对于电子商务系统而言,每个需要权限验证的方法都是一个单独的join point。由于权限验证将在每个方法执行前执行,所以对于这一系列join point,只需要定义一个point cut。当系统执行到join point处时,将根据定义去查找对应的point cut,然后执行这个横切关注点需要实现的逻辑,即advice。而point cut和advice,就组合成了一个权限管理aspect。

图2.5 AOP动态横切的技术实现

由于aspect是一个封装的对象,我们可以定义这样一个aspect: private static aspect AuthorizationAspect{……}

然后在这个aspect中定义point cut,在point cut中,定义了需要截取上下文消息的方法,例如:

private pointcutauthorizationExecution(): execution(public void OrderManager.AddOrder(Order))||

北大青鸟中关村

execution(public void OrderManager.DeleteOrder(Order))|| execution(public void ProductManager.AddProduct(Product))|| execution(public void ProductManager.DeleteProduct(Product));由于权限验证是在订单管理方法执行之前完成,因此在before advice中,定义权限检查:

before(): authorizationExecution(){ if!(permissions.Verify(Permission.ADMIN)){ throw new UnauthorizedException();} } 通过定义了这样一个完整的aspect,当系统调用OrderManager或ProductManager的相关方法时,就触发了point cut,然后调用相应的advice逻辑。如此以来,OrderManager和ProductManager模块就与权限管理模块完全解除了依赖关系,同时也消除了传统设计中不可避免的权限判断的重复代码。这对于建立一个松散耦合、可扩展的系统软件是非常有利的。2.2.2.3 静态横切

静态横切和动态横切的区别在于它不修改一个给定对象的执行行为。相反,它允许通过引入附加的方法字段和属性来修改对象的结构。此外,静态横切可以把扩展和实现附加到对象的基本结构中。在AOP实现中,通常将静态横切称为introduce或者mixin。

北大青鸟中关村

静态横切在AOP技术中,受到的关注相对较少。事实上,这一技术蕴含的潜力是巨大的。使用静态横切,架构师和设计者能用一种真正面向对象的方法有效地建立复杂系统的模型。静态横切允许您不用创建很深的层次结构,以一种本质上更优雅、更逼真于现实结构的方式,插入跨越整个系统的公共行为。尤其是当开发应用系统时,如果需要在不修改原有代码的前提下,引入第三方产品和API库,则静态横切技术将发挥巨大的作用。

举例来说,当前已经实现了一个邮件收发系统,其中类Mail完成了收发邮件的功能。但在产品交付后,发现该系统存在缺陷,在收发邮件时,未曾实现邮件地址的验证功能。现在,第三方产品已经提供了验证功能的接口IValidatable: public interface IValidatable { boolValidateAddress();} 我们可以利用设计模式中的Adapter模式,来完成对第三方产品API的调用。我们可以定义一个新的类MailAdapter,该类实现了IValidatable接口,同时继承了Mail类:

public class MailAdapter:Mail,IValidatable { public boolValidateAddress(){ if(this.getToAddress()!= null){ return true;

北大青鸟中关村

} else { return false;} } } 通过引入MailAdapter类,原来Mail对象完成的操作,将全部被MailAdapter对象取代。然而,此种实现方式虽然能解决引入新接口的问题,但类似下面的代码,却是无法编译通过的: Mail mail = new Mail();IValidatable validate =((IValidatable)mail).ValidateAddress();必须将第一行代码作如下修改: Mail mail = new MailAdapter();利用AOP的静态横切技术,可以将IValidatable接口织入到原有的Mail类中,这是一种非常形象的introduce功能,其实现仍然是在aspect中完成: importcom.acme.validate.Validatable;public aspect MailValidateAspect { declare parents: Mail implements IValidatable;

北大青鸟中关村

publicbooleanMail.validateAddress(){ if(this.getToAddress()!= null){ return true;} else { return false;} } } 静态横切的方法,并没有引入类似MailAdapter的新类,而是通过定义的MailValidateAspect方面,利用横切技术为Mail类introduce了新的方法ValidateAddress(),从而实现了Mail的扩展。因此如下的代码完全可行。Mail mail = new Mail();IValidatable validate =((IValidatable)mail).ValidateAddress();2.3 AOP技术的优势

AOP技术的优势是显而易见的。在面向对象的世界里,人们提出了各种方法和设计原则来保障系统的可复用性与可扩展性,以期建立一个松散耦合、便于扩展的软件系统。例如GOF提出的“设计模式”,为我们提供了设计的典范与准则。设计模式通过最大程度的利用面向对象的特性,诸如利用继承、多态,对责任

北大青鸟中关村

进行分离、对依赖进行倒置,面向抽象,面向接口,最终设计出灵活、可扩展、可重用的类库、组件,乃至于整个系统的架构。在设计的过程中,通过各种模式体现对象的行为、暴露的接口、对象间关系、以及对象分别在不同层次中表现出来的形态。然而鉴于对象封装的特殊性,“设计模式”的触角始终在接口与抽象中大做文章,而对于对象内部则无能为力。

通过“横切”技术,AOP技术就能深入到对象内部翻云覆雨,截取方法之间传递的消息为我所用。由于将核心关注点与横切关注点完全隔离,使得我们能够独立的对“方面”编程。它允许开发者动态地修改静态的OO模型,构造出一个能够不断增长以满足新增需求的系统,就象现实世界中的对象会在其生命周期中不断改变自身,应用程序也可以在发展中拥有新的功能。设计软件系统时应用AOP技术,其优势在于:

(一)在定义应用程序对某种服务(例如日志)的所有需求的时候。通过识别关注点,使得该服务能够被更好的定义,更好的被编写代码,并获得更多的功能。这种方式还能够处理在代码涉及到多个功能的时候所出现的问题,例如改变某一个功能可能会影响到其它的功能,在AOP中把这样的麻烦称之为“纠结(tangling)”。

(二)利用AOP技术对离散的方面进行的分析将有助于为开发团队指定一位精于该项工作的专家。负责这项工作的最佳人选将可以有效利用自己的相关技能和经验。

(三)持久性。标准的面向对象的项目开发中,不同的开发人员通常会为某项服务编写相同的代码,例如日志记录。随后他们会在自己的实施中分别对日志

北大青鸟中关村

进行处理以满足不同单个对象的需求。而通过创建一段单独的代码片段,AOP提供了解决这一问题的持久简单的方案,这一方案强调了未来功能的重用性和易维护性:不需要在整个应用程序中一遍遍重新编写日志代码,AOP使得仅仅编写日志方面(logging aspect)成为可能,并且可以在这之上为整个应用程序提供新的功能。

上一篇:农村土地使用权转让下一篇:大一新生如何进入大学

相关推荐