Java语言程序设计郑莉第八章课后习题答案.docx
《Java语言程序设计郑莉第八章课后习题答案.docx》由会员分享,可在线阅读,更多相关《Java语言程序设计郑莉第八章课后习题答案.docx(23页珍藏版)》请在冰点文库上搜索。
Java语言程序设计郑莉第八章课后习题答案
Java语言程序设计
第八章课后习题答案
1.进程和线程有何区别,Java是如何实现多线程的。
答:
区别:
一个程序至少有一个进程,一个进程至少有一个线程;线程的划分尺度小于进程;进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
Java程序一般是继承Thread类或者实现Runnable接口,从而实现多线程。
2.简述线程的生命周期,重点注意线程阻塞的几种情况,以及如何重回就绪状态。
答:
线程的声明周期:
新建-就绪-(阻塞)-运行--死亡
线程阻塞的情况:
休眠、进入对象wait池等待、进入对象lock池等待;
休眠时间到回到就绪状态;在wait池中获得notify()进入lock池,然后获得锁棋标进入就绪状态。
3.随便选择两个城市作为预选旅游目标。
实现两个独立的线程分别显示10次城市名,每次显示后休眠一段随机时间(1000毫秒以内),哪个先显示完毕,就决定去哪个城市。
分别用Runnable接口和Thread类实现。
(注:
两个类,相同一个测试类)
//Runnable接口实现的线程runable类
publicclassrunnableimplementsRunnable{
privateStringcity;
publicrunnable(){}
publicrunnable(Stringcity){
this.city=city;
}
publicvoidrun(){
for(inti=0;i<10;i++){
System.out.println(city);
try{
//休眠1000毫秒。
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
//Thread类实现的线程thread类
publicclassrunnableextendsThread{
privateStringcity;
publicrunnable(){}
publicrunnable(Stringcity){
this.city=city;
}
publicvoidrun(){
for(inti=0;i<10;i++){
System.out.println(city);
try{
//休眠1000毫秒。
Thread.sleep(1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
}
}
}
//test8_3
publicclasstest8_3{
publicstaticvoidmain(String[]args){
//将创建一个线程对象,这个对象接受一个实现了Runnable接口。
实际上这里也就是使用run()方法
runnabler1=newrunnable("广州");
runnabler2=newrunnable("乌鲁木齐");
Threadt1=newThread(r1);
Threadt2=newThread(r2);
//启动线程
t1.start();
t2.start();
}
}
运行结果分别为:
4.编写一个多线程程序实现如下功能:
线程A和线程B分别在屏幕上显示信息“…start”后,调用wait等待;线程C开始后调用sleep休眠一段时间,然后调用notifyall,使线程A和线程B继续运行。
线程A和线程B恢复运行后输出信息“…end”后结束,线程C在判断线程B和线程A结束后自己结束运行。
//test8_4
publicclasstest8_4{
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[]){
test8_4test=newtest8_4();
//A、B两线程一起输入start和输出end,不过中间有C让线程休眠2秒,没法全部一次性输出,
//之后再唤醒,让AB继续输出下半部分end
test.A.start();
test.B.start();
test.C.start();
}
}
运行结果:
5.实现一个数据单元,包括学号和姓名两部分。
编写两个线程,一个线程往数据单元中写,另一个线程往外读。
要求没写一次就往外读一次。
//Data类
importjava.util.Scanner;
publicclassData{
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类
publicclassReadextendsThread{
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();
}
}
}
//test8_5类
publicclasstest8_5{
publicstaticvoidmain(String[]args){
Datadata=newData();
newRead(data).start();
newWrite(data).start();
}
}
运行结果:
6.创建两个不同优先级的线程,都从1数到10000,看看哪个数得快。
(注:
线程的优先级别越高低与执行速度没有绝对关系!
)
//Count类
publicclassCountextendsThread{
intwhich;
intn=10000;
publicCount(intwhich){
this.which=which;
}
publicvoidrun(){
for(inti=1;i<=n;i++){
if(i==n){
System.out.println(which+"号进程"+"结束!
");
}
}
}
}
//test8_6
publicclasstest8_6{
publicstaticvoidmain(String[]args){
Countcount1=newCount
(1);
Countcount2=newCount
(2);
Threadt1=newThread(count1);
Threadt2=newThread(count2);
t1.setPriority
(2);//1号进程优先级是2
t2.setPriority(8);//2号进程优先级是8
t1.start();
t2.start();
}
}
运行结果:
都有可能。
7.编写一个Java程序,以说明较高优先级的线程通过调用sleep方法,使较低优先级的线程获得运行的机会。
(这里可以借鉴课本例8—13)
//TestThread类
publicclassTestThreadextendsThread{
privateinttick=1;
privateintnum;
publicTestThread(inti){
this.num=i;
}
publicvoidrun(){
while(tick<){
tick++;
if((tick%50000)==0){
System.out.println("Thread#"+num+",tick="+tick);
yield();
try{
sleep
(1);
}catch(Exceptione){
}
}
}
}
}
//test8_7
publicclasstest8_7{
publicstaticvoidmain(String[]args){
TestThread[]runners=newTestThread[2];
for(inti=0;i<2;i++){
runners[i]=newTestThread(i);
}
runners[0].setPriority
(2);
runners[1].setPriority(5);
for(inti=0;i<2;i++){
runners[i].start();
}
}
}
运行结果:
8.主线程控制新线程的生命,当主线程运行一段时间后,控制新线程死亡,主线程继续运行一段时间后结束。
(注:
main函数就是主线程,程序里其他的Thread都属于子线程。
可以参考课本的例8—1)
//SonThread类
publicclassSonThreadextendsThread{
privateintnum;
publicSonThread(intnum){
this.num=num;
}
publicvoidrun(){
inti=num;
intresult=1;
System.out.println("newthreadstart.");
/*while(i>0){
result=result*i;
i--;
}*/
System.out.println("thenewthreadof"+num+"is"+result);
System.out.println("newthreadends");
}
}
//test8_8
publicclasstest8_8{
publicstaticvoidmain(String[]args){
System.out.println("maintreadstart.");
SonThreadnewThread=newSonThread(10);
newThread.start();
//;浪费时间的循环
inti=1;
while(i<=){
i++;
}
newThread.stop();//结束新进程
System.out.println("mainthreadends");
}
}
运行结果:
(这个结果很难把握,通常都会出现2那样的结果,知道原理就好。
)
2
9.用两个线程模拟存、取货物。
一个线程往一对象里放货物(包括品名、价格),另外一个线程取货物。
分别模拟“放一个、取一个”和“放若干个、取若干个”两种情况。
//Good货物类
publicclassGood{
Stringname;
intprice;
publicGood(){
}
publicGood(Stringname,intprice){
this.name=name;
this.price=price;
}
publicGood(Goodg){
this.name=g.name;
this.price=g.price;
}
}
//WareHouse仓库类
importjava.util.ArrayList;
importjava.util.List;
importjava.util.Scanner;
publicclassWareHouse{
Goodgood=null;
Scannerin=newScanner(System.in);
Listlist=newArrayList();//用来存放商品对象
intcount;//想存入商品的个数
booleanavailable=true;
publicWareHouse(){
}
publicWareHouse(intcount){
this.count=count;
}
publicWareHouse(Listlist){
this.count=count;
for(inti=0;ithis.list.add((Good)list.get(i));
}
}
publicsynchronizedvoidsaveGood(){
if(available==false){
try{
wait();
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
for(inti=0;iStringn;
intp;
System.out.println("请输入"+(i+1)+"号商品的名称:
");
n=in.next();
System.out.println("价格:
");
p=in.nextInt();
good=newGood(n,p);
list.add(good);
}
available=false;
notify();
}
publicsynchronizedvoidtakeGood(){
if(available==true){
try{
wait();
}catch(InterruptedExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
for(inti=0;igood=(Good)list.get(i);
System.out.print((i+1)+"号商品的名称为:
"+good.name);
System.out.println("\t价格为:
"+good.price);
}
available=true;
notify();
}
}
//Save存货物类
publicclassSaveextendsThread{
WareHousewareHouse=null;
publicSave(WareHousew){
this.wareHouse=w;
}
publicvoidrun(){
wareHouse.saveGood();
}
}
//Take取货物类
publicclassTakeextendsThread{
WareHousewareHouse=null;
publicTake(WareHousew){
this.wareHouse=w;
}
publicvoidrun(){
wareHouse.takeGood();
}
}
//test8_9测试类
importjava.util.Scanner;
publicclasstest8_9{
publicstaticvoidmain(String[]args){
Scannerin=newScanner(System.in);
System.out.println("请输入仓库的容量:
");
inti=in.nextInt();
WareHousewareHouse=newWareHouse(i);
ThreadsaveGood=newSave(wareHouse);
ThreadtakeGood=newTake(wareHouse);
saveGood.start();
takeGood.start();
}
}
运行结果:
10.用两个线程模拟对话,任何一个线程都可以随时收发信息。
(这道题本人搞不清楚,暂且用网上的给大家参考下。
听说要用到:
Socket.getInputStream()获取输入流用于“接收”
Socket.getOutputStream()获取输出流用于“发送”
)
//test8_10
importjava.io.*;
import.*;
importjava.util.*;
publicclasstest8_10{
publicstaticvoidmain(String[]args){
try{
//establishserversocket
ServerSockets=newServerSocket(8189);
//waitforclientconnection
Socketincoming=s.accept();
try{
InputStreaminStream=incoming.getInputStream();
OutputStreamoutStream=incoming.getOutputStream();
Scannerin=newScanner(inStream);
PrintWriterout=newPrintWriter(outStream,true);
out.println("Hello!
EnterBYEtoexit.");
//echoclientinput
booleandone=false;
while(!
done&&in.hasNextLine()){
Stringline=in.nextLine();
out.println("Echo:
"+line);
if(line.trim().equals("BYE"))
done=true;
}
}finally{
incoming.close();
}
}catch(IOExceptione){
e.printStackTrace();
}
}
}