教师对学生的项目评分——进程的同步与互斥一、课题内容和要求课题内容:在一个班上有S个学生。每个学生都要做一个项目,每一个项目由K个老师一起评分。总共有M个老师。每个老师最多给N个项目评分。其中,S*K=M*N。在项目结束后,老师们提供T分钟用来检查学生们的项目。检查每一个学生的项目需要用时D分钟。其中,TD。每一个学生的项目由K个老师共同来检查。在T分钟的时间段内,学生可以在任何时间进入教室(random),除了在最后的D分钟内。所有的老师一直保持工作状态直到他检查完N个项目或者是T分钟过去后。T分钟过去后,所有的老师和同学都必须离开教室。另外,在T分钟结束前的D分钟内(即在最后的D分钟内),如果有任何老师或者是学生都处在没有任务的状态下,都必须离开教室,因为已经没有时间让他完成任务了(因为一个项目检查的时间是整整D分钟)。要求:用一个程序来模拟上面描述的作业检查过程。每一个学生和每一个老师应该用不同的线程来完成。可以选用C、C++和Java作为开发语言,但是考虑到专业课程设计I的实验大纲,请尽可能使用Java语言。二、需求和思路分析当一个学生进入教室后,他立即开始找K个没有任务的老师(一次找一个老师,假如没有空闲的老师,则等到有老师为止),找齐K个老师之后给老师检查,然后离开教室。刚开始每一个老师都是处于空闲状态直到他被学生找到,被学生找到后只能等待,直到学生找齐K个老师(在等待学生找其他老师的时间里,他是不能接受其他同学检查作业的请求的),当学生找齐K个老师后,老师们执行完检查任务,然后重新变成空闲状态。每个老师在总共检查了N个学生的作业后,离开教室。并不保证所有的学生都在T分钟的时间段内完成了检查,还要注意不能发生死锁问题。设计一个学生线程,一个老师线程,并将共享代码块用synchronized锁起来,使在同一时间,只有一个学生线程使用此代码块。一个学生线程执行下面的步骤:(1)选择一个进入的时间(random()%(T-D))minutes;(2)进入教室;(3)选择K个空闲的老师,若找不齐,则等待;(4)找齐后,做D分钟的检查;(5)检查完毕离开教室。一个老师线程执行下面的步骤:(1)在教室中空闲;(2)直到被一个学生选择后等待(所有K个老师聚集);(3)等待结束项目检查开始;(4)做D分钟的项目检查;(1)—(4)步骤重复N次……(5)N次检查完毕或者T分钟时间到,离开教室。三、概要设计学生线程(Student.java):classStudentextendsThread{publicintK,J,T,D;//每个学生找K个老师检查第J个同学publicintnumTeacher;//传递教师人数publicintnumK=0;//统计找到老师数Teacher[]teacher;//传递教师指针操控教师数组publicint[]pos;//创建存储选择老师的下标的数组,供释放使用Randomran1=newRandom();intn;//存放最小的需求初值为开始时需要老师数publicStudent(intK,intJ,intT,intD,Teacher[]teacher,intnumTeacher);//构造函数publicvoidrun();//学生线程需要执行的代码}老师线程(Teacher.java):publicclassStudentextendsThread{publicintK,J,T,D;//每个学生找K个老师检查第J个同学publicintnumTeacher;//传递教师人数publicintnumK=0;//统计找到老师数Teacher[]teacher;//传递教师指针操控教师数组publicint[]pos;//创建存储选择老师的下标的数组,供释放使用Randomran1=newRandom();intn;//存放最小的需求初值为开始时需要老师数publicStudent(intK,intJ,intT,intD,Teacher[]teacher,intnumTeacher);//构造函数publicvoidrun();//老师线程需要执行的代码}Check.java:classcheck{publicstaticint[]ava;//存放老师还可检查的项目数publicstaticintnumstu;publicstaticint[]need;//存放学生需要的老师数publicstaticintu=1;publicstaticvoidmain(String[]args);//初始化S,K,T,D,M,N}四、详细设计具体代码:Check.java:importjava.util.Scanner;publicclasscheck{publicstaticint[]ava;//存放老师还可检查的项目数publicstaticintnumstu;publicstaticint[]need;//存放学生需要的老师数publicstaticintu=1;publicstaticvoidmain(String[]args){ints,m,n,k,t,d;System.out.println(请输入学生人数:);//sScannercs=newScanner(System.in);s=cs.nextInt();numstu=s;need=newint[s];//申请与学生人数相当的数组空间System.out.println(请输入老师人数:);//mm=cs.nextInt();ava=newint[m];//初始化可用老师数System.out.println(请输入每个老师完成任务数:);//nn=cs.nextInt();System.out.println(每个项目检查老师数:);//kk=cs.nextInt();System.out.println(总时间:);//tt=cs.nextInt();System.out.println(验收时间:);//dd=cs.nextInt();Timecounttc=newTimecount(d);tc.start();Teachertea[]=newTeacher[m];for(intj=0;jm;j++){System.out.println(老师+j+准备);tea[j]=newTeacher(n,j,d);ava[j]=1;//老师是否可用tea[j].start();}Studentstu[]=newStudent[s];for(intj=0;js;j++){System.out.println(学生+j+准备);stu[j]=newStudent(k,j,t,d,tea,m);need[j]=k;//stu[j].start();}}}Student.java:importjava.util.Random;publicclassStudentextendsThread{publicintK,J,T,D;//每个学生找K个老师检查第J个同学publicintnumTeacher;//传递教师人数publicintnumK=0;//统计找到老师数Teacher[]teacher;//传递教师指针操控教师数组publicint[]pos;//创建存储选择老师的下标的数组,供释放使用Randomran1=newRandom();intn;//存放最小的需求初值为开始时需要老师数publicStudent(intK,intJ,intT,intD,Teacher[]teacher,intnumTeacher){this.K=K;this.J=J;this.teacher=teacher;this.numTeacher=numTeacher;this.pos=newint[K];//申请检查老师人数相当的空间this.T=T;this.D=D;this.n=K;}publicvoidrun(){Randomrd=newRandom();Stringstr=newString();try{Thread.sleep(rd.nextInt(T-D));//控制首次进入时间}catch(InterruptedExceptione){}System.out.println(学生+J+进入教室);while(numKK&&check.u==1){for(intj=0;jnumTeacher&&numKK;j++){synchronized(str){if(teacher[j].P==1&&teacher[j].numNteacher[j].N)//当前老师未选中且未完成{//任务一定在此比较老师线程//执行完while后不一定立刻执行下一次循环不能立刻去判断numNN从而未结束线程intm=0;//每次都得重新赋值不然数据每次叠加check.need[J]--;//需要老师数减一check.ava[j]=0;//对应老师检查的项目数减一for(intl=0;lnumTeacher;l++)if(check.ava[l]!=0){m++;//可选老师数//System.out.println(laoshi+l);}for(intk=0;kcheck.numstu;k++){if(k!=J){if(check.need[k]n&&check.need[k]!=0)//有问题自己若是为0n=check.need[k];//最少需要老师数}else{if(check.need[k]n)n=check.need[k];}}if(n=m){teacher[j].P=0;teacher[j].numN++;pos[numK]=j;//选中老师的下标加入存储数组numK++;System.out.println(学生+J+选择老师+teacher[j].Q);}else{check.need[J]++;check.ava[j]=1;}}}}}for(inti=0;iK;i++)//启动所以选中老师{teacher[pos[i]].beg=1;}if(numK==K)System.out.println(学生+J+检查完毕);elseSystem.out.println(学生+J+强制退出);}}Teacher.java:publicclassTeacherextendsThread{publicintN;//每个老师检查N个项目publicintDD;publicintnumN=0;//统计已经检查项目数publicintQ;//第Q个老师publicintP=1;//指示有木有选中publicintbeg=0;//启动publicTeacher(intN,intQ,intDD){this.N=N;this.Q=Q;this.DD=DD;}publicvoidrun(){while(numN=N&&check.u==1){if(beg==1){try{Thread.sleep(DD);}catch(InterruptedExceptione){}if(numNN){check.ava[Q]=1;System.out.println(老师+Q+完成检查项目数+numN);P=1;beg=0;}else{System.out.println(老师+Q+完成检查项目数+numN);numN++;//跳出循环因为numN++在Student里面完成}}}if(numN==(N+1)){System.out.println(老师+Q+完成任务);}elseSystem.out.println(老师+Q+强制退出);}}Timeout.java:publicclassTimecountextendsThread{publicinttime;publicTimecount(inttime){this.time=time;}publicvoidrun(){try{Thread.sleep(time*100);}catch(Interrup