并行计算实验报告一.docx
《并行计算实验报告一.docx》由会员分享,可在线阅读,更多相关《并行计算实验报告一.docx(13页珍藏版)》请在冰点文库上搜索。
并行计算实验报告一
并行计算实验报告一
江苏科技大学
计算机科学与工程学院
实验报告
评定成绩指导教师实验课程:
并行计算
宋英磊实验名称:
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实验总结