并行计算实验报告一.docx
- 文档编号:10900093
- 上传时间:2023-02-23
- 格式:DOCX
- 页数:12
- 大小:27.96KB
并行计算实验报告一.docx
《并行计算实验报告一.docx》由会员分享,可在线阅读,更多相关《并行计算实验报告一.docx(12页珍藏版)》请在冰豆网上搜索。
并行计算实验报告一
江苏科技大学
计算机科学与工程学院
实验报告
评定成绩
指导教师
宋英磊
实验课程:
并行计算
实验名称:
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实验总结
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 并行 计算 实验 报告
![提示](https://static.bdocx.com/images/bang_tan.gif)