天津理工大学Java实验四实验报告文档格式.docx
《天津理工大学Java实验四实验报告文档格式.docx》由会员分享,可在线阅读,更多相关《天津理工大学Java实验四实验报告文档格式.docx(17页珍藏版)》请在冰豆网上搜索。
实验内容(应包括实验题目、实验要求、实验任务等)
本实验要求你使用wait/notify和其他线程控制方法创建一个打印机管理器(printermanager)。
要求你创建几个并发线程产生打印作业,一个打印管理器线程处理这些作业。
下面是一个可能的输出结果:
C:
Printmanagerisstartingup.
Waitingonajobtoprint.
P:
Addingjob'
Fred#1'
tothequeue
Startingjob'
Elizabeth#1'
Simon#1'
Completedjob'
Fred#2'
Simon#2'
Fred#3'
Elizabeth#2'
Simon#3'
Fred#4'
Fred#5'
Elizabeth#3'
Printmanagerishalted.
实验过程与实验结果(可包括实验实施的步骤、算法描述、流程、结论等)
一、实验步骤与算法描述
1、定义PrintJob类
(1)基于上述UML类图定义PrintJob类,代表一个打印作业。
2、定义Producer类
(2)基于上述UML类图定义Producer类。
它必须实现Runnable接口。
(3)写一个构造方法初始化4个实例变量。
(4)run方法必须创建数量为numberOfJobs的打印作业(PrintJob对象)。
根据producerName属性和作业号给每个作业起一个作业名(即jobName=producerName#N)。
每个打印作业的页数pages由sizeOfJobs属性确定。
(5)用Printer对象的addJob方法把打印作业加到打印机管理器的打印队列中去。
该方法可能抛出FullQueueException异常(队列满异常),要求编程时处理这种异常情况,直至队列非满为止,然后把作业加到队列中去。
(6)在相邻两次打印期间,producer睡眠delayBetweenJobs长时间。
3、定义Printer类
(7)基于上述UML类图定义Printer类。
(8)写构造方法初始化属性。
打印队列大小为5,即最多能容纳5个作业。
(9)printQueue属性是一个FIFO队列,它包含所有的被提交的打印作业。
Queue是一个接口,代表FIFO队列。
CircularQueue实现该接口。
FullQueueException和EmptyQueueException异常分别可以由addBack和removeFront方法抛出。
(10)写public、synchronized方法addJob。
该方法可能抛出FullQueueException异常。
在该方法中,加一个作业以后要通知Printer对象可以继续打印。
(11)写private、synchronized方法getJob。
该方法可能抛出EmptyQueueException异常。
(12)写public、synchronized方法halt(停止)。
该方法设置stateIsRunning属性为false。
StateIsRunning属性代表打印机是否正在运行。
(13)写run方法。
它是打印管理器的核心。
它始终处于连续循环之中,直到stateIsRunning=false为止。
它从队列中取打印作业,输出Startingjob‘作业名’,然后处理作业(睡眠一段时间,500毫秒/页×
页数),然后打印Completedjob‘作业名’。
如果队列中没有作业,输出Waitingonajobtoprint并等待。
当打印机被halt后,应先处理剩余作业,然后输出Printmanagerishalted并退出run方法。
(14)本题最困难的部分是wait和notify的使用。
4、创建TestPrinter程序
(15)这个类只包含main方法。
(16)让main方法创建3个Producer对象,它们有不同的打印特征:
作业大小(5页-25页),作业间的延迟(2秒-10秒)。
下面是模拟用的三个Producer对象:
producerName
numberOfJobs
sizeOfJobs
delayBetweenJobs
Fred
5
8秒
Elizabeth
3
25
20秒
Simon
10秒
(17)为打印机管理器创建一个线程。
设置它的优先级为最大,然后启动该线程。
(18)为每个producer创建线程,然后启动该线程。
(19)用join方法等待每个producer线程结束。
(20)最后,停止打印机管理器。
二、实验结果截图:
三、实验分析总结
本次实验中,主要练习编译了Java中多线程有关的程序。
通过本次实验,对Java中多线程的实现与控制操作有了更深一步的理解。
以后也还需要多加练习,能更加熟悉。
同时,编写程序中遇到问题再所难免,应耐心探究其中的原因,从出现问题的地方起,并联系前后程序,仔细推敲,逐个排查。
直到最终搞清为止。
附录(源程序清单)
//FullQueueException类
packageEx;
publicclassFullQueueExceptionextendsIndexOutOfBoundsException
{
privatestaticfinallongserialVersionUID=1L;
StringERROR_INFO;
FullQueueException(Strings)
{
this.ERROR_INFO=newString(s);
}
publicStringtoString()
return"
FullQueueException"
+ERROR_INFO;
}
//EmptyQueueException类
publicclassEmptyQueueExceptionextendsIndexOutOfBoundsException
EmptyQueueException(Strings)
EmptyQueueException"
//CircleQueue类
importjava.util.Arrays;
publicclassCircleQueue<
T>
privateintDEFAULT_SIZE=5;
privateintcapacity;
privateObject[]elementData;
privateintfront=0;
privateintrear=0;
publicCircleQueue()
capacity=DEFAULT_SIZE;
elementData=newObject[capacity];
publicCircleQueue(Telement)
this();
elementData[0]=element;
rear++;
}
publicCircleQueue(Telement,intinitSize)
this.capacity=initSize;
publicintsize()
if(isEmpty())
{
return0;
}
returnrear>
front?
rear-front:
capacity-(front-rear);
publicvoidaddBack(Telement)throwsFullQueueException
if(rear==front&
&
elementData[front]!
=null)
thrownewFullQueueException("
队列已满的异常"
);
elementData[rear++]=element;
rear=rear==capacity?
0:
rear;
publicTremoveFront()throwsEmptyQueueException
thrownewEmptyQueueException("
空队列异常"
ToldValue=(T)elementData[front];
elementData[front++]=null;
front=front==capacity?
front;
returnoldValue;
publicTelement()throwsEmptyQueueException
if(isEmpty()){
return(T)elementData[front];
publicbooleanisEmpty()
//rear==front且rear处的元素为null
returnrear==front&
elementData[rear]==null;
publicvoidclear()
Arrays.fill(elementData,null);
front=0;
rear=0;
//PrintJob类
publicclassPrintJob
privateStringjobName;
privateintpages;
publicPrintJob(StringsjN,intspg)
this.jobName=newString(sjN);
this.pages=spg;
publicStringgetName()
returnthis.jobName;
publicintgetPages()
returnthis.pages;
//Producer类
importjava.util.Queue;
publicclassProducerimplementsRunnable
privateintsizeOfJobs;
privateintnumberOfJobs;
privateintdelayBetweenJobs;
privateStringproducerName;
privateThreadPrintThread=null;
publicProducer(intss,intsn,intsd,Stringspn,Threadt){
this.sizeOfJobs=ss;
this.numberOfJobs=sn;
this.delayBetweenJobs=sd;
this.producerName=newString(spn);
this.PrintThread=t;
publicvoidrun(){
for(inti=0;
i<
this.numberOfJobs;
i++){
PrintJobpj=newPrintJob(this.producerName+"
#"
+i,this.sizeOfJobs);
try{
Printer.getInstance().addJob(pj);
Thread.sleep(this.delayBetweenJobs);
}catch(InterruptedExceptione){
e.printStackTrace();
}catch(FullQueueExceptione){
System.out.println("
无法添加打印任务启动Printer"
+e);
}
}
//Printer类
publicclassPrinterimplementsRunnable
staticprivateCircleQueue<
PrintJob>
printQueue=newCircleQueue<
();
staticprivatebooleanstateIsRunning=true;
privatestaticfinalPrinterPRNTR_ONLY=newPrinter();
staticprivatebooleanwhileend=false;
privatePrinter(){}
publicstaticPrintergetInstance(){
returnPRNTR_ONLY;
publicsynchronizedvoidhalt()
if(Printer.stateIsRunning){
System.out.println("
C:
Printmanagerishalted."
Printer.stateIsRunning=false;
publicvoidaddJob(PrintJobjob)throwsFullQueueException,InterruptedException
synchronized(printQueue)
try
{
this.printQueue.addBack(job);
}
catch(FullQueueExceptione)
try
{
printQueue.notify();
printQueue.wait();
}
catch(InterruptedExceptione1)
{
e1.printStackTrace();
}
System.out.println("
[1]P:
Addingjob"
+job.getName()+"
tothequeue"
privatePrintJobgetJob()throwsEmptyQueueException{
PrintJobp=null;
synchronized(printQueue){
while(p==null&
stateIsRunning){
try{
p=this.printQueue.element();
Printer.printQueue.removeFront();
}catch(EmptyQueueExceptione){
try{
printQueue.notifyAll();
printQueue.wait(500);
}catch(InterruptedExceptione1){
e1.printStackTrace();
}
System.out.println("
Waitingonajobtoprint."
+stateIsRunning);
returnp;
Printmanagerisstartingup."
while(stateIsRunning){
PrintJobpjob=null;
pjob=this.getJob();
System.out.println("
[2]C:
Startingjob"
+pjob.getName());
Thread.sleep(500*pjob.getPages());
[3]C:
Completedjob"
}catch(EmptyQueueExceptione){
break;
}catch(InterruptedExceptione){
//TestPrinter类
publicclassTestPrinter
publicstaticvoidmain(String[]args){
PrinterPRNT_P=Printer.getInstance();
ThreadTHRD_P=newThread(PRNT_P);
THRD_P.setPriority(10);
Producerpd1=newProducer(5,2,5,"
A"
THRD_P);
Producerpd2=newProducer(5,2,5,"
B"
Producerpd3=newProducer(5,3,5,"
C"
Threadthrd_A=newThread(pd1);
Threadthrd_B=newThread(pd2);
Threadthrd_C=newThread(pd3);
thrd_A.start();
thrd_B.start();
thrd_C.start();
THRD_P.start();
try{
thrd_A.join();
thrd_B.join();
thrd_C.join();
catch(InterruptedExceptione1)
{
e1.printStackTrace();
try
Thread.sleep(10000);
catch(InterruptedExceptione)
{
e.printStackTrace();
PRNT_P.halt();