java 实验八 多线程 实验报告.docx

上传人:b****5 文档编号:3862888 上传时间:2022-11-26 格式:DOCX 页数:25 大小:286.79KB
下载 相关 举报
java 实验八 多线程 实验报告.docx_第1页
第1页 / 共25页
java 实验八 多线程 实验报告.docx_第2页
第2页 / 共25页
java 实验八 多线程 实验报告.docx_第3页
第3页 / 共25页
java 实验八 多线程 实验报告.docx_第4页
第4页 / 共25页
java 实验八 多线程 实验报告.docx_第5页
第5页 / 共25页
点击查看更多>>
下载资源
资源描述

java 实验八 多线程 实验报告.docx

《java 实验八 多线程 实验报告.docx》由会员分享,可在线阅读,更多相关《java 实验八 多线程 实验报告.docx(25页珍藏版)》请在冰豆网上搜索。

java 实验八 多线程 实验报告.docx

java实验八多线程实验报告

实验八多线程

实验目标:

(1)掌握使用Thread的子类创建线程;掌握实现Runable接口来实现多线程;

(2)掌握线程之间的数据共享;

(3)掌握线程之间的同步方法;

(4)掌握线程之间的通信方法。

实验任务:

1、选择答题(请将答案标成红色,如(AB)):

1.下面关于线程的说法正确的是(ABD)。

A)Java支持多线程机制。

B)一个线程创建并启动后,它将执行自己的run()方法,如果通过派生Thread类实现多线程,则需要在子类中重新定义run()方法,把需要执行的代码写run()方法中;如果通过实现Runnable接口实现多线程,则要编写run()方法的方法体。

C)要在程序中实现多线程,必须导入Thread类:

importjava.lang.Thread;

D)一个程序中的主类不是Thread的子类,该类也没有实现Runnable接口,则这个主类运行是不能控制主线程的休眠。

2.如果程序中创建了两个线程,一个的优先级是Thread.MAX_PRIORITY,另一个的优先级是正常的默认优先级,下列陈述哪个是对的?

(A)

A)正常优先级的线程不运行,直到拥有最高优先级的线程停止运行。

B)即使拥有最高优先级的线程结束运行,正常优先级的线程也不会运行。

C)正常优先级的线程优先运行。

D)上述说法都不对。

3.下面哪个是Runnable接口中的抽象方法(D)?

A)startB)stopC)yieldD)run

4.编译下面的程序,得到的结果是(C)。

publicclassAimplementsRunnable{

publicvoidrun(){

System.out.println("OK.");

}

publicstaticvoidmain(String[]args){

ThreadTh=newThread(newA());

Th.start();

}

}

A)程序不能编译,产生异常。

B)程序能编译运行,但没有任何结果输出。

C)程序能编译运行,输出结果:

OK.。

D)上面说法都不对。

5.为什么处于激活状态的线程可能不是当前正在执行的线程?

(BCD)

(备注:

激活(unblock):

如果阻塞线程的事件发生,则该线程被激活并进入就绪队列。

A)因为已经执行完run()方法。

B)线程正在等待键盘输入。

C)该线程调用了wait()方法。

D)该线程正在休眠状态。

2.下面是一个多线程的程序:

publicclassSimpleThreadextendsThread{

publicSimpleThread(Stringstr){

super(str);

}

publicvoidrun(){

for(inti=0;i<10;i++){

System.out.println(i+""+getName());

try{

sleep((long)(Math.random()*1000));

}catch(InterruptedExceptione){}

}

System.out.println("DONE!

"+getName());

}

}

publicclassTwoThreadsTest{

publicstaticvoidmain(String[]args){

newSimpleThread("Jamaica").start();

newSimpleThread("Fiji").start();

}

}

 

(1)输入该程序并运行之,体会多线程的程序的编写方法。

输入该程序后执行结果截图如下:

(2)将该程序该为通过实现Runnable接口的方式实现多线程。

改为Runnable后程序代码如下:

packagezi;

publicclassEx8_2_2{

publicstaticvoidmain(Stringargs[])

{

Movemove=newMove();

move.test1.start();

move.test2.start();

}

}

classMoveimplementsRunnable

{

Threadtest1,test2;

Move()

{

test1=newThread(this);

test1.setName("Jamaica");

test2=newThread(this);

test2.setName("Fiji");

}

publicvoidrun()

{

if(Thread.currentThread()==test1)

{

for(inti=1;i<=10;i++)

{

System.out.println(test1.getName());

}

}

else

{

for(inti=1;i<=5;i++)

{

System.out.println(test2.getName());

}

}

}

}

运行结果截图如下:

3,课本270页课后习题第4题。

下面给出一个范例(只供参考):

(1)这个程序运行就是一个进程,根据要求要设计三个线程,首先给出一个协助三个线程通信的类:

(2)接下来根据要求设计A线程和B线程,因为两个线程功能相同,所以可以是同一个类的不同实例对象,设计该类如下:

我们可以看到,基本设计方法与书本并无区别,同样为了协调三个线程之间通信,我们使用了一个通信类,根据规范操作,每个线程对通信类实例进行操作时,需要进行同步,就是

synchronized(){//获得锁旗标

具体执行就是根据题意,调用wait()等待,注意wait()跟sleep()是有区别的,前者会自动释放CPU和同步锁旗标,而后者会释放CPU,但不会释放同步锁旗标,在这里,由于三个线程都使用了同一个同步对象,因此,需要使用wait()(当然大家也可以不使用通信对象来完成这个题目)。

(请大家详细看课本262页的解析)

Wait()之后,就将自己至于就绪等待队列,然后

是唤醒其他线程,很明显在当前进程中,一共才三个线程,A和B进入了wait状态,它们唤醒的就只有C了,于是C出场。

(3)关于C的类设计结构基本跟上面A、B类一样,就是在run方法里面根据要求编写,首先就是sleep一段时间,参数单位是毫秒,然后调用notifyall让A和B继续运行,A和B运行结束之后,自然会回到C运行,这时如何按题意来判断其他线程都已结束呢?

我们可以再

.wait();一次,作用是C放弃当前CPY与锁旗标,让其他线程先运行完毕,这个时候如果C线程重新开始回到CPU执行,意味着没有其他线程了,也就是可以判断AB已经执行完了,于是自己也愉快的结束运行。

关键代码见下:

(4)测试类一如既往与书本一样,如下:

该题代码如下:

packagezi;

publicclassEx8_3{

ThreadA=newThread("A"){

publicvoidrun(){

Wait("A");

}

};

ThreadB=newThread("B"){

publicvoidrun(){

Wait("B");

}

};

ThreadC=newThread("C"){

publicvoidrun(){

while(true){

if(!

A.isAlive()&&!

B.isAlive())

return;

try{

Thread.sleep(2000);

}catch(InterruptedExceptione){

e.printStackTrace();

}

notifyall();

}

}

};

publicsynchronizedvoidWait(Stringname){

System.out.println(name+"start");

try{

wait();

}catch(InterruptedExceptione){

e.printStackTrace();

}

System.out.println(name+"end");

}

publicsynchronizedvoidnotifyall(){

notifyAll();

}

publicstaticvoidmain(Stringargs[]){

Ex8_3test=newEx8_3();

//A、B两线程一起输入start和输出end,不过中间有C让线程休眠2秒,没法全部一次性输出,

//之后再唤醒,让AB继续输出下半部分end

test.A.start();

test.B.start();

test.C.start();

}

}

其运行结果截图如下:

4,课本270页课后习题第5题,记得要实现线程互斥(同步)。

这个跟书本例题差不多的设计方式,记得是生产者与消费者模型,书本展示了两种实现方式,建议采用第二种比较规范(256页例8-9),这里纯模仿就可以,具体不细说了,大家看说,纯模仿,看结果。

依题意,该题代码如下:

packagezi;

importjava.util.Scanner;

classData{

StringstudentId;

Stringname;

booleanavailable=false;//判断是读是写

Scannerin=newScanner(System.in);//定义一个输入对象

publicsynchronizedvoidread()

{

if(available)

try

{

wait();

}

catch(Exceptione)

{

}

System.out.printf("请输入学号:

");

try

{

studentId=in.next();

}

catch(Exceptione)

{

System.out.println("输入学号出错!

");

}

System.out.printf("请输入姓名:

");

try

{

name=in.next();

}

catch(Exceptione)

{

System.out.println("输入姓名出错!

");

}

System.out.println();

available=true;

notify();

}

publicsynchronizedvoidwrite()

{

if(!

available)

try

{

wait();

}

catch(Exceptione)

{

}

System.out.println("输出学生学号:

"+studentId+"姓名:

"+name+"\n");

available=false;

notify();

}

}

//Read类

classReadextendsThread{

Datad1=null;

publicRead(Datad){

this.d1=d;

}

publicvoidrun(){

while(true)

{

d1.read();

}

}

}

//Write类

classWriteextendsThread{

Datad2=null;

publicWrite(Datad)

{

this.d2=d;

}

publicvoidrun()

{

while(true)

{

d2.write();

}

}

}

publicclassEx8_4{

publicstaticvoidmain(String[]args){

Datadata=newData();

newRead(data).start();

newWrite(data).start();

}

}

 

执行结果截图如下:

 

5,课本270页课后习题第10题。

这一题主要运用wait()和notify()来同步,这个程序本身是一个进程,里面根据题意一共设计只有两个线程,一个wait,然后notify自然就是启动另一个线程,如此交替运行,实现侦听。

注意这两个线程功能相同,所以可以是同一个类的不同对象,这个类如下(参考,大家可以自己编写):

classMyThreadextendsThread{

Stringname;

StringBuffersendString;

StringBufferrecvString;

MyThread(Stringname,StringBuffersendString,StringBufferrecvString){

this.name=name;

this.sendString=sendString;

this.recvString=recvString;

}

@Override

publicvoidrun(){

//循环100次,每次循环都sleep一段随机事件,然后收发消息

for(inti=0;i<100;i++){

inttime=(int)(Math.random()*100);

try{

sleep(time);

}

catch(Exceptione){

e.printStackTrace();

}

sendMsg();

recvMsg();

}

}

//发送消息

publicvoidsendMsg(){

synchronized(sendString){

while(sendString.length()>0){

try{

sendString.wait();

}

catch(Exceptione){

e.printStackTrace();

}

}

doublecontent=Math.random();

sendString.append(name+content);

System.out.println(name+"send"+content);

sendString.notify();

}

}

//接收消息

publicvoidrecvMsg(){

synchronized(recvString){

while(recvString.length()==0){

try{

recvString.wait();

}

catch(Exceptione){

e.printStackTrace();

}

}

System.out.println(name+"recv"+recvString);

recvString.delete(0,recvString.length());

recvString.notify();

}

}

}

请详细分析看懂以上代码,然后自己修改适合自己的类,最后编写测试类,实现题意功能,运行结果见下:

我选择了模拟银行账户类,代码如下:

packagezi;

classMbankCompex{//模拟银行账户类

privatestaticintsum=2000;

publicsynchronizedstaticvoidtake(intk){//限定take为同步方法

inttemp=sum;

temp-=k;

try{

Thread.sleep((int)(100*Math.random()));}

catch(InterruptedExceptione){}

sum=temp;

System.out.println(Thread.currentThread()+"sum="+sum);

}

}

classUserGetMoneyextendsThread{//模拟用户取款的线程类

publicvoidrun(){

for(inti=1;i<=4;i++){

MbankCompex.take(100);

}

}

}

publicclassEx8_5{//调用线程的主类

publicstaticvoidmain(String[]args){

UserGetMoneyu1=newUserGetMoney();

UserGetMoneyu2=newUserGetMoney();

u1.start();

u2.start();

}

}

运行结果截图如下:

6【选做】,编写一个应用程序,除了主线程外,还有两个线程:

first和second。

first负责模拟一个红色的按钮从坐标(10,60)运动到(100,60);second负责模拟一个绿色的按钮从坐标(100,60)运动到(200,60),输出模拟过程。

(要结合第9章的画图知识)

 

依题意,代码如下:

packagezi;

importjavax.swing.*;

importjava.awt.*;

publicclassEx8_6extendsJFrameimplementsRunnable{

Threadfirst=newThread(this,"1");

ThreadSecond=newThread(this,"2");

JButtongreen=newJButton();

JButtonred=newJButton();

JLabellgreen=newJLabel("100,60");

JLabellred=newJLabel("10,60");

intx=10,y=60,x1=100;

Ex8_6(){

setLayout(null);

green.setBackground(Color.green);

green.setBounds(100,60,30,20);

red.setBackground(Color.red);

red.setBounds(10,60,30,20);

lred.setBounds(10,50,50,10);

lgreen.setBounds(100,80,50,10);

add(green);add(red);

add(lgreen);add(lred);

setSize(300,250);

setVisible(true);

first.start();

}

publicvoidrun(){

Stringcr=Thread.currentThread().getName();

if(cr.equals("1")){

while(x<100){

try{

x+=10;

red.setLocation(x,y);

lred.setLocation(x,y-10);

lred.setText(x+",60");

Thread.sleep(200);

}catch(Exceptione){}

}

Second.start();

}

else{

while(x1<200){

try{

x1+=10;

green.setLocation(x1,y);

lgreen.setLocation(x1,y+20);

lgreen.setText(x1+",60");

Thread.sleep(200);

}catch(Exceptione){}

}

}

}

publicstaticvoidmain(Stringargs[]){

newEx8_6();

}

}

 

其运行结果如下所示:

 

该程序UML图截图如下:

7【选做】,广深和谐号每列火车可售出800张票,现设有4个人工售票口以及10台自动售票机,假设每次操作售出都是一张票,人工售票口平均每10秒(这个数字是为了方便调试测试,与现实有差距)售出一张,自动售票机平均20秒售出一张,请开设14个子线程模拟售出该800张票(模拟过程输出结果的后50行截图即可),并给出售出总时间,并按售出票数从多到少将各窗口排序输出,并给出各窗口售票张数。

提示:

(1),请参考书上相似的例子,基本模型与该例子相似,如题目有不完善处,请依据该模型自行完善

(2),要通过命名标记人工售票窗1号-4号,自动售票机1号-10号,以方便区别。

8【选做】在某KFC餐厅中一共有6个服务窗口,以供应奥尔良烤翅为例,1号至6号窗口每10秒(这个数字是为了方便调试测试,与现实有差距)分别卖出的对数分别是{2,1,1,3,2,1},而制作奥尔良烤翅的师傅有两名,一名每1分钟制作30对,一名每30秒制作20对。

请问卖出300对烤翅需要多长时间?

两名师傅分别生产多少对?

6个窗口分别卖出多少对?

请模拟这一过程(最后50对截图即可)。

提示:

(1)请参考书上相似的例子,基本模型相似,如题目有不完善处,请依据该模型自行完善;

(2)要通过命名标记各不同的生产者与消费者,记得生产者与消费者要同步。

(3)每10秒卖出一对,可以采用sleep,让线程等待来模拟。

测试时可以将所有数值等同缩小,其间逻辑关系不变,这样就不用等待很长时间久可以模拟。

如10秒统一换成1秒,那1分钟就是6秒,30秒就是3秒,如此类推。

测试完毕后将数据调为要求数据即可。

(4)注意当300对买完后,需要中止各个子线程并输出结果。

9【选做】.编写一个堆栈类MyStack,类中定义含5个元素的整型数组,并定义了两个同步(synchronized)方法:

入栈操作方法push(intk),用来向堆栈中压入一个整数;出栈操作方法intpop(),用来从栈顶弹出一个整数。

方法push和pop中,通过wait()方法和notify()方法协调压入和弹出操作,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 数学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1