实验五多线程程序设计汽院含答案.docx
- 文档编号:5711474
- 上传时间:2023-05-09
- 格式:DOCX
- 页数:38
- 大小:44.36KB
实验五多线程程序设计汽院含答案.docx
《实验五多线程程序设计汽院含答案.docx》由会员分享,可在线阅读,更多相关《实验五多线程程序设计汽院含答案.docx(38页珍藏版)》请在冰点文库上搜索。
实验五多线程程序设计汽院含答案
实验五多线程程序设计
实验目的
1.掌握Java语言中多线程编程的基本方法
2.掌握Runnable接口实现多线程的方法
3.掌握Thread类实现多线程的用法
实验导读
1.进程和线程的概念
进程是程序一次动态执行的过程,对应从代码加载、执行到执行结束这样一个完整的过程,也是进程自身从产生、发展到消亡的过程。
线程是比进程更小的执行单元,一个进程在执行过程中,可以产生多个线程。
每个线程都有自身的产生、执行和消亡的过程。
2.线程的状态与生命周期
●新建:
当一个Thread类或其子类的对象被声明并创建时,新生的线程对象处于新建状态。
此时它已经有了相应的内存空间和其他资源。
●运行:
线程创建之后就具备了运行的条件,一旦轮到它来享用CPU资源时,即JVM将CPU使用权切换给该线程时,此线程的就可以脱离创建它的主线程独立开始自己的生命周期了(即run方法执行的过程)。
●中断:
有4种原因的中断,CPU资源从当前线程切换给其他线程、执行了sleep(intmillsecond)方法、执行了wait()方法、进入阻塞状态。
●死亡:
run方法结束。
3.线程的创建
在Java语言中,与线程支持密切相关的是java.lang.Thread类和java.lang.Runnable接口。
Runnable接口定义很简单,只有一个run方法。
任何一个类如果希望自己的实例能够以线程的形式执行,都可以来实现Runnable接口。
继承Thread类和实现Runnable接口,都可以用来创建Thread对象,效果上并没有什么不同。
继承Thread类的方法很明显的缺点就是这个类不能再继承其他的类了,而实现Runnable接口不会有这个麻烦。
另外,在继承Thread类的代码中,this其实就是指当前正在运行的线程对象,如果使用实现Runnable接口的方式,要得到当前正在执行的线程,需要使用Thread.currentThread()方法。
线程创建后仅仅是占有了内存资源,在JVM管理的线程中还没有这个线程,此线程必须调用start()方法(从父类继承的方法)通知JVM,这样JVM就会知道又有一个新一个线程排队等候切换了。
注意:
多次启动一个线程,或者启动一个已经运行的线程对象是非法的,会抛出IllegalThreadStateException异常对象。
4.线程的优先级
同一时刻在等待队列中的线程会有很多个,它们各自任务的重要性有所不同。
为了加以区分,使工作安排和资源分配时间更为合理,每个线程可以被赋予不同的优先级,让任务比较急的线程拥有更高的优先级,从而更快地进入执行状态。
Java中提供了10个等级的线程优先级,最低为Thread.MIN_PRIORITY=1,最高为Thread.MAX_PRIORITY=10,默认优先级为Thread.NORM_PRIORITY=5。
使用Thread类中的setPriority(int)方法可以为线程指定优先级。
5.线程的常用方法
●start()方法:
线程调用该方法将启动线程,使之从新建状态进入就绪队列排队,一旦轮到它来享用CPU资源时,就可以脱离创建它的线程独立开始自己的生命周期了。
●run()方法:
Thread类的run()方法与Runnable接口中的run()方法的功能和作用相同,都用来定义线程对象被调度之后所执行的操作,都是系统自动调用而用户程序不得引用的方法。
系统的Thread类中,run()方法没有具体内容,所以用户程序需要创建自己的Thread类的子类,并重写run()方法来覆盖原来的run()方法。
当run方法执行完毕,线程就变成死亡状态。
●sleep(intmillsecond)方法:
现程占有CPU期间,执行sleep方法来使自己放弃CPU资源,休眠一段时间。
休眠时间的长短由sleep方法的参数决定,millsecond是毫秒为单位的休眠时间。
如果线程在休眠时被打断,JVM就抛出InterruptedException异常。
因此,必须在try~catch语句块中调用sleep方法。
●isAlive()方法:
线程处于“新建”状态时,线程调用isAlive()方法返回false。
当一个线程调用start()方法,并占有CUP资源后,该线程的run方法就开始运行,在线程的run方法结束之前,即没有进入死亡状态之前,线程调用isAlive()方法返回true。
当线程进入“死亡”状态后(实体内存被释放),线程仍可以调用方法isAlive(),这时返回的值是false。
一个已经运行的线程在没有进入死亡状态时,不要再给线程分配实体,由于线程只能引用最后分配的实体,先前的实体就会成为“垃圾”,并且不会被垃圾收集机收集掉。
●currentThread()方法:
currentThread()方法是Thread类中的类方法,可以用类名调用,该方法返回当前正在使用CPU资源的线程。
●interrupt()方法:
intertupt方法经常用来“吵醒”休眠的线程。
当一些线程调用sleep方法处于休眠状态时,一个占有CPU资源的线程可以让休眠的线程调用interrupt方法“吵醒”自己。
6.线程的同步
线程同步是指几个线程都需要调用一个同步方法(使用关键字synchronized修饰的方法)。
当一个线程A使用一个synchronized修饰的方法时,其他线程想使用这个方法时就必须等待,直到线程A使用完该方法(除非线程A使用wait主动让出CPU资源)。
一个线程在使用的同步方法中时,可能根据问题的需要,必须使用wait()方法使本线程等待,暂时让出CPU的使用权,并允许其它线程使用这个同步方法。
其它线程如果在使用这个同步方法时如果不需要等待,那么它用完这个同步方法的同时,应当执行notifyAll()方法通知所有的由于使用这个同步方法而处于等待的线程结束等待。
●挂起:
有时候两个线程并不是同步的,即不涉及都需要调用一个同步方法,但线程也可能需要暂时的挂起。
所谓挂起一个线程就是让线程暂时让出CPU的使用权限,暂时停止执行,但停止执行的持续时间不确定,因此不能使用sleep方法暂停线程。
挂起一个线程需使用wait方法,即让准备挂起的线程调用wait方法,主动让出CPU的使用权限.
●恢复:
为了恢复该线程,其它线程在占有CUP资源期间,让挂起的线程的目标对象执行notifyAll()方法,使得挂起的线程继续执行;如果线程没有目标对象,为了恢复该线程,其它线程在占有CUP资源期间,让挂起的线程调用notifyAll()方法,使挂起的线程继续执行。
实验内容
1.汉字识别程序
编写一个Java应用程序,在主线程中再创建一个Frame类型的窗口,在该窗口中再创建一个线程giveWord。
线程giveWord每隔6秒钟给出一个汉字,用户使用一种汉字输入法将该汉字输入到文本框中。
请按模板要求,将代码补充完整。
WordThread.java
importjava.awt.*;
publicclassWordThreadextendsThread{
charword;
Labelcom;
WordThread(Labelcom){
=com;
}
publicvoidrun(){
while(true){
word=(char)(Math.random()*(29968-19968)+19968);
System.out.println(word);
com.setText(""+word);
try{
【补充代码】//调用sleep方法使得线程中断6000豪秒
}catch(InterruptedExceptione){}
}
}
}
ThreadFrame.java
publicclassThreadFrameextendsFrameimplementsActionListener{
LabelwordLabel;
Buttonbutton;
TextFieldinputText,scoreText;
【补充代码】//用WordThread声明一个giveWord对象
intscore=0;
ThreadFrame(){
wordLabel=newLabel("",Label.CENTER);
wordLabel.setFont(newFont("",Font.BOLD,72));
button=newButton("开始");
inputText=newTextField(3);
scoreText=newTextField(5);
scoreText.setEditable(false);
【补充代码】//创建giveWord,将wordLabel传递给WordThread构造方法的参数
button.addActionListener(this);
inputText.addActionListener(this);
add(button,BorderLayout.NORTH);
add(wordLabel,BorderLayout.CENTER);
PanelsouthP=newPanel();
southP.add(newLabel("输入标签所显示的汉字后回车:
"));
southP.add(inputText);
southP.add(scoreText);
add(southP,BorderLayout.SOUTH);
setBounds(100,100,350,180);
setVisible(true);
validate();
addWindowListener(newWindowAdapter(){
publicvoidwindowClosing(WindowEvente){
System.exit(0);
}
});
}
publicvoidactionPerformed(ActionEvente){
if(e.getSource()==button){
if(!
(【补充代码】))//giveWord调用方法isAlive()
{
giveWord=newWordThread(wordLabel);
}
try{
【补充代码】//giveWord调用方法start()
}catch(Exceptionexe){
}
}elseif(e.getSource()==inputText){
if(inputText.getText().equals(wordLabel.getText())){
score++;
}
scoreText.setText("得分:
"+score);
inputText.setText(null);
}
}
}
WordThread.java
publicclassThreadWordMainClass{
publicstaticvoidmain(Stringargs[]){
newThreadFrame();
}
}
答案代码:
WordThread.java
importjava.awt.*;
publicclassWordThreadextendsThread{
charword;
Labelcom;
WordThread(Labelcom){
=com;
}
publicvoidrun(){
while(true){
word=(char)(Math.random()*(29968-19968)+19968);
System.out.println(word);
com.setText(""+word);
try{
sleep(6000);//调用sleep方法使得线程中断6000豪秒
}catch(InterruptedExceptione){}
}
}
}
ThreadFrame.java
publicclassThreadFrameextendsFrameimplementsActionListener{
LabelwordLabel;
Buttonbutton;
TextFieldinputText,scoreText;
WordThreadgiveWord;//用WordThread声明一个giveWord对象
intscore=0;
ThreadFrame(){
wordLabel=newLabel("",Label.CENTER);
wordLabel.setFont(newFont("",Font.BOLD,72));
button=newButton("开始");
inputText=newTextField(3);
scoreText=newTextField(5);
scoreText.setEditable(false);
giveWord=newWordThread(wordLabel);//创建giveWord,将wordLabel传递给WordThread构造方法的参数
button.addActionListener(this);
inputText.addActionListener(this);
add(button,BorderLayout.NORTH);
add(wordLabel,BorderLayout.CENTER);
PanelsouthP=newPanel();
southP.add(newLabel("输入标签所显示的汉字后回车:
"));
southP.add(inputText);
southP.add(scoreText);
add(southP,BorderLayout.SOUTH);
setBounds(100,100,350,180);
setVisible(true);
validate();
addWindowListener(newWindowAdapter(){
publicvoidwindowClosing(WindowEvente){
System.exit(0);
}
});
}
publicvoidactionPerformed(ActionEvente){
if(e.getSource()==button){
if(!
(giveWord.isAlive()))//giveWord调用方法isAlive()
{
giveWord=newWordThread(wordLabel);
}
try{
giveWord.start();//【补充代码】//giveWord调用方法start()
}catch(Exceptionexe){
}
}elseif(e.getSource()==inputText){
if(inputText.getText().equals(wordLabel.getText())){
score++;
}
scoreText.setText("得分:
"+score);
inputText.setText(null);
}
}
}
WordThread.java
publicclassThreadWordMainClass{
publicstaticvoidmain(Stringargs[]){
newThreadFrame();
}
}
2.双线程接力
编写一个应用程序,除了主线程外,还有两个线程:
first和second。
first负责模拟一个红色的按钮从坐标(10,60)运动到(100,60);second负责模拟一个绿色的按钮从坐标(100,60)运动到(200,60)。
阅读并分析以下程序,将程序中的代码补充完整,编译并运行程序,查看结果。
MoveButton.java
importjava.awt.*;
importjava.awt.event.*;
publicclassMoveButtonextendsFrameimplementsRunnable,ActionListener
{【补充代码】//用Thread类声明first,second两个线程对象
ButtonredButton,greenButton,startButton;
intdistance=10;
MoveButton()
{【补充代码】//创建first线程,当前窗口做为该线程的目标对象
【补充代码】//创建first线程,当前窗口做为该线程的目标对象
redButton=newButton();
greenButton=newButton();
redButton.setBackground(Color.red);
greenButton.setBackground(Color.green);
startButton=newButton("start");
startButton.addActionListener(this);
setLayout(null);
add(redButton);
redButton.setBounds(10,60,15,15);
add(greenButton);
greenButton.setBounds(100,60,15,15);
add(startButton);
startButton.setBounds(10,100,30,30);
setBounds(0,0,300,200);
setVisible(true);
validate();
addWindowListener(newWindowAdapter()
{publicvoidwindowClosing(WindowEvente)
{System.exit(0);
}
}
);
}
publicvoidactionPerformed(ActionEvente)
{try{first.start();
second.start();
}
catch(Exceptionexp){}
}
publicvoidrun()
{while(true)
{if(【补充代码】)//判断当前占有CPU资源的线程是否是first
{moveComponent(redButton);
try{Thread.sleep(20);
}
catch(Exceptionexp){}
}
if(【补充代码】)//判断当前占有CPU资源的线程是否是second
{moveComponent(greenButton);
try{Thread.sleep(10);
}
catch(Exceptionexp){}
}
}
}
publicsynchronizedvoidmoveComponent(Componentb)
{
if(Thread.currentThread()==first)
{while(distance>100&&distance<=200)
try{wait();
}
catch(Exceptionexp){}
distance=distance+1;
b.setLocation(distance,60);
if(distance>=100)
{b.setLocation(10,60);
notifyAll();
}
}
if(Thread.currentThread()==second)
{while(distance>=10&&distance<100)
try{wait();
}
catch(Exceptionexp){}
distance=distance+1;
b.setLocation(distance,60);
if(distance>200)
{distance=10;
b.setLocation(100,60);
notifyAll();
}
}
}
}
MoveButtonMainClass.java
publicclassMoveButtonMainClass
{publicstaticvoidmain(Stringargs[])
{newMoveButton();
}
}
答案:
MoveButton.java
importjava.awt.*;
importjava.awt.event.*;
publicclassMoveButtonextendsFrameimplementsRunnable,ActionListener
{/**
*
*/
privatestaticfinallongserialVersionUID=1L;
Threadfirst,second;//用Thread类声明first,second两个线程对象
ButtonredButton,greenButton,startButton;
intdistance=10;
MoveButton()
{first=newThread(this);//创建first线程,当前窗口做为该线程的目标对象
second=newThread(this);//创建first线程,当前窗口做为该线程的目标对象
redButton=newButton();
greenButton=newButton();
redButton.setBackground(Color.red);
greenButton.setBackground(Color.green);
startButton=newButton("start");
startButton.addActionListener(this);
setLayout(null);
add(redButton);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验五 多线程程序设计汽院含答案 实验 多线程 程序设计 汽院含 答案