并行计算实验报告一.docx

上传人:b****8 文档编号:10900093 上传时间:2023-02-23 格式:DOCX 页数:12 大小:27.96KB
下载 相关 举报
并行计算实验报告一.docx_第1页
第1页 / 共12页
并行计算实验报告一.docx_第2页
第2页 / 共12页
并行计算实验报告一.docx_第3页
第3页 / 共12页
并行计算实验报告一.docx_第4页
第4页 / 共12页
并行计算实验报告一.docx_第5页
第5页 / 共12页
点击查看更多>>
下载资源
资源描述

并行计算实验报告一.docx

《并行计算实验报告一.docx》由会员分享,可在线阅读,更多相关《并行计算实验报告一.docx(12页珍藏版)》请在冰豆网上搜索。

并行计算实验报告一.docx

并行计算实验报告一

江苏科技大学

计算机科学与工程学院

实验报告

 

评定成绩

指导教师

宋英磊

实验课程:

并行计算

实验名称:

Java多线程编程

学号:

姓名:

班级:

完成日期:

2014年04月22日

 

1.1实验目的

(1)掌握多线程编程的特点;

(2)了解线程的调度和执行过程;

(3)  掌握资源共享访问的实现方法。

1.2知识要点

1.2.1线程的概念

(1)   线程是程序中的一个执行流,多线程则指多个执行流;

(2)   线程是比进程更小的执行单位,一个进程包括多个线程;

(3)   Java语言中线程包括3部分:

虚拟CPU、该CPU执行的代码及代码所操作的数据。

(4)   Java代码可以为不同线程共享,数据也可以为不同线程共享;

1.2.2线程的创建

(1)方式1:

实现Runnable接口

Thread类使用一个实现Runnable接口的实例对象作为其构造方法的参数,该对象提供了run方法,启动Thread将执行该run方法;

(2)  方式2:

继承Thread类

重写Thread类的run方法;

1.2.3线程的调度

(1)线程的优先级

●        取值范围1~10,在Thread类提供了3个常量,MIN_PRIORITY=1、MAX_PRIORITY=10、NORM_PRIORITY=5;

●        用setPriority()设置线程优先级,用getPriority()获取线程优先级;

●        子线程继承父线程的优先级,主线程具有正常优先级。

(2)线程的调度:

采用抢占式调度策略,高优先级的线程优先执行,在Java中,系统按照优先级的级别设置不同的等待队列。

1.2.4线程的状态与生命周期

说明:

新创建的线程处于“新建状态”,必须通过执行start()方法,让其进入到“就绪状态”,处于就绪状态的线程才有机会得到调度执行。

线程在运行时也可能因资源等待或主动睡眠而放弃运行,进入“阻塞状态”,线程执行完毕,或主动执行stop方法将进入“终止状态”。

1.2.5线程的同步--解决资源访问冲突问题

(1)对象的加锁

所有被共享访问的数据及访问代码必须作为临界区,用synchronized加锁。

对象的同步代码的执行过程如图14-2所示。

synchronized关键字的使用方法有两种:

●        用在对象前面限制一段代码的执行,表示执行该段代码必须取得对象锁。

●        在方法前面,表示该方法为同步方法,执行该方法必须取得对象锁。

(2)wait()和notify()方法

用于解决多线程中对资源的访问控制问题。

●        wait()方法:

释放对象锁,将线程进入等待唤醒队列;

●        notify()方法:

唤醒等待资源锁的线程,让其进入对象锁的获取等待队列。

(3) 避免死锁

指多个线程相互等待对方释放持有的锁,并且在得到对方锁之前不会释放自己的锁。

1.3上机测试下列程序

样例1:

利用多线程编程编写一个龟兔赛跑程序。

∙  乌龟:

速度慢,休息时间短;

∙  兔子:

速度快,休息时间长;

【参考程序1】字符方式下实现方案

classAnimalextendsThread{

 intspeed; //速度

publicAnimal(Stringstr,intspeed){

    super(str);  //线程名用动物名代表

    this.speed=speed;

 }

 publicvoidrun(){

   intdistance=0;

   intsleepTime;

   while(distance<=1000){

     System.out.println(getName()+"isat"+distance);

     try{

        distance+=speed; //每次跑的距离简单用速度计算

        sleepTime=(int)(speed+Math.random()*speed);//速度快休息时间要长

        sleep(sleepTime);

     }catch(InterruptedExceptione){}

   }

 }

}

publicclassRace{

  publicstaticvoidmain(Stringarg[]){

    Animala1,a2;

    a1=newAnimal("rabit",100);

    a2=newAnimal("turtle",20);  

    a2.setPriority(Thread.MAX_PRIORITY);//让乌龟的运行优先级更高

    a1.start();

    a2.start();

 }

}

【编程技巧】

(1)   速度快,跑的距离增加也快,这里简单地将速度加到距离上,未考虑跑的时间;

(2)   为了让乌龟得到更多的运行机会,采取两项措施,一让线程的睡眠时间与速度成正比,二是让乌龟得到更高的优先级。

【参考程序2】—图形方式下,图14-3为程序的运行演示。

publicclassrunnerextendsAppletimplementsRunnable{

   intBeginX=10,EndX=200;  //起点和终点的x坐标

intRabbitX=BeginX,RabbitY=100; //兔子的起点

intTortoiseX=BeginX,TortoiseY=200; //乌龟的起点

intRabbitRestTime=800,TortoiseRestTime=50;//各自休息时间

intRabbitSpeed=15,TortoiseSpeed=1;  //各自速度

intstate=0; //比赛状态,0代表比赛进行中,1代表兔子赢,2代表乌龟赢

Threadrabbit;

Threadtortoise;

publicvoidinit()   {

      rabbit=newThread(this,"rabbit");//创建名为rabit的线程

      tortoise=newThread(this,"tortoise");//创建名为tortoise的线程

   }

   publicvoidpaint(Graphicsg){

       g.drawString("龟",TortoiseX,TortoiseY);

       g.drawString("兔",RabbitX,RabbitY);

       g.setColor(Color.red);

       for(intj=70;j<=230;j+=10)g.drawString("|",EndX+8,j);//绘制终点线

       g.setColor(Color.black);

       if(state==1)g.drawString("兔子赢了!

!

",250,300);

       elseif(state==2)g.drawString("乌龟赢了!

!

",250,300);

   }

   publicvoidstart(){

       rabbit.start();

       tortoise.start();

   }

   publicvoidrun(){

       StringcurrentRunning;

       while(state==0){

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

//得到当前线程的名程

           if(currentRunning.equals("rabbit")){ //是兔子

try{

Thread.sleep((int)(Math.random()*RabbitRestTime));

}

               catch(InterruptedExceptione){}

               RabbitX+=RabbitSpeed;

               if(RabbitX>EndX)RabbitX=EndX;

           }

           elseif(currentRunning.equals("tortoise")){//是乌龟

try{

                    Thread.sleep((int)(Math.random()*TortoiseRestTime));

}

               catch(InterruptedExceptione){}

               TortoiseX+=TortoiseSpeed;

               if(TortoiseX>EndX)TortoiseX=EndX;

           }

           if (RabbitX==EndX)state=1;

           elseif(TortoiseX==EndX)state=2;

           repaint();

       }

   }  

}

【编程技巧】

(1)   创建两个代表兔子和乌龟的线程,根据线程名决定各自的速度和休息时间。

(2)   根据是否到达终点决定state值的变化;

(3)   线程的run方法内的循环条件是state值为0。

样例2:

编写选号程序,在窗体中安排6个标签,每个标签上显示0~9之间的一位数字,每位数字用一个线程控制其变化,点击“停止”按钮则所有标签数字停止变化。

【参考程序】

importjava.awt.*;

importjava.awt.event.*;

publicclassMyFrameextendsFrame{

MyLabelx[]=newMyLabel[6];//安排6个标签,每个标签显示1个数字

Buttoncontrol;

publicMyFrame(Stringtitle){

super(title);

Paneldisp=newPanel();

disp.setLayout(newFlowLayout());

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

x[i]=newMyLabel();

disp.add(x[i]);

newThread(x[i]).start();

}

add("Center",disp);

control=newButton("停止");

add("North",control);

pack();

setVisible(true);

control.addActionListener(newActionListener(){

publicvoidactionPerformed(ActionEvente){

for(inti=0;i<6;i++)

x[i].stop=true;

}

}

);

}

publicstaticvoidmain(Stringargs[]){

newMyFrame("Test");

}

classMyLabelextendsLabelimplementsRunnable{

intvalue;

booleanstop=false;

publicMyLabel(){

super("number");

value=0;

}

publicvoidrun(){

for(;;){

value=(int)(Math.random()*10);//产生一个0到9的数字

setText(Integer.toString(value));

try{

Thread.sleep(500);

}

catch(InterruptedExceptione){}

if(stop)//停止标记为true,退出循环,结束运行

break;

}

}

}

}【编程技巧】

(1)将每个标签定义为线程方式运行,在运行中利用随机数产生数字显示。

(2)线程体为一个循环语句,只有当stop标记变量为true,则停止;

(3)主程序中将所有标签定义存入一个数组,这样可以方便地对其进行控制,例如,在点击“停止”按钮时将所有标签对象的stop属性值设置为true。

1.4上机完成编程任务

任务描述:

完成下列编程任务,并将代码与实验报告一起交给教师。

✧     基本题(必做)

1)编写一个可变颜色的标签,用一个按钮控制颜色的改变与停止。

点击按钮颜色停止变化,再点击该按钮颜色又变化。

颜色的变化可用随机数确定。

2)有一个南北向的桥,只能容纳一个人,现桥的两边分别有10人和12人,编制一个多线程序让这些人到达对岸,每个人用一个线程表示,桥为共享资源。

在过桥的过程中显示谁在过桥及其走向。

3)编写一个图片播放程序,图片的文件名为file01.jpg,file02.jpg,…filen.jpg,其中n由命令行输入,要求用多线程自动播放。

✧     提高题(选做其中一个)

1)编制一个秒针计时器,在画面包含一个文本框,显示秒针值,安排一个“开始”和“结束”按钮,点击“开始”按钮则开始计时,点击“结束”停止计时。

时间的确定可借助日历对象实例方法实现,用get(Calendar.SECOND)方法得到秒值,用get(Calendar.MINUTE)方法得到分值,用get(Calendar.HOUR)方法得到小时值。

计算从“开始”到“当前”的时间差即可确定花费的秒数。

【进一步思考】如何将秒针计时器设计为图形界面,绘制一个圆形秒表,秒表的一圈为60秒,根据花费的时间显示秒针的变化。

2)编写生产者/消费者问题的应用程序。

生产者以0~200ms的速度随机产生30个小写字母,消费者以0~2s的速度取出字母,并显示在屏幕上。

3)利用多线程求解某范围素数,每个线程负责10000范围.

  线程1找1000-10000

  线程2找10001-20000

  线程3找20001-30000

  另开辟一线程专门接收其他线程发送给它的数据(创建管道输入输出流),直到3个线程发送的数据均结束(结束标记)为止,接受的数据以文本形式写入到文件xyz.dat中。

1.5思考题(必做)

任务描述:

完成实验后,完成下列多选题

1)什么原因可导致线程停止执行。

A.有更高优先级的线程开始执行;

B.线程调用了wait()方法;

C.线程调用了yield()方法;

D.线程调用了pause()方法;

E.线程调用了sleep()方法。

2)哪个方法是实现Runnable接口所需的?

A.wait()      B.run()       C.stop()

D.update()    E.resume()

3)以下代码的调试结果为?

publicclassBgroundextendsThread{

publicstaticvoidmain(Stringargv[]){

     Bgroundb=newBground();

     b.run();

 }

publicvoidstart(){

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

        System.out.println("Valueofi="+i);

    }

 }

}

A.编译错误,没有定义线程的run方法;

B.由于没有定义线程的run方法,而出现运行错误;

C.编译通过,运行输出values0to9

D.编译通过,运行无输出

4)有关线程的叙述正确的有:

A.通过继承Thread类或实现Runnable接口,可以获得对类中方法的互斥锁定。

B.可以获得对任何对象的互斥锁定。

C.线程通过调用对象的synchronized方法可取得对象的互斥锁定。

D.线程调度算法是平台独立的。

5)以下哪个是线程类的方法?

A.yield()

B.sleep(longmsec)

C.go()

D.stop()

6) 以下哪个最准确描述synchronized关键字?

A.允许两线程并行运行,而且互相通信;

B.保证在某时刻只有一个线程可访问方法或对象;

C.保证允许两个或更多处理同时开始和结束;

D.保证两个或更多线程同时开始和结束。

1.7实验总结

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

当前位置:首页 > 法律文书 > 调解书

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

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