Java语言程序设计第10章习题参考答案

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

习题十参考答案
10.1什么是进程?什么是线程?二者有什么联系和区别?
进程是程序的一次动态执行过程,它对应了从代码加载、执行到执行完毕的一个完整过程,这个过程也是进程从产生、发展到消亡的过程。

线程是比进程更小的执行单位。

一个进程在其执行过程中,可以产生多个线程,形成多条执行线索。

每条线索,即每个线程也有它自身的产生、存在和消亡的过程,是一个动态的概念。

在进程运行过程中,每个进程都有一段专用的内存区域,并以PCB作为它存在的标志;与进程不同的是,线程间可以共享相同的内存单元(包括代码与数据),并利用这些共享单位来实现数据交换、实时通信与必要的同步操作。

10.2线程有哪些基本状态?试描述它们的相互转换过程。

新建状态、就绪状态、运行状态、阻塞状态、死亡状态。

相互转换的过程如图:
10.3创建线程的方式有哪几种?请举例说明。

1.继承自Thread类,代码逻辑写在子线程中,需要重写run()方法,主线程里start()就可以了。

public class ExtendsThread extends Thread{
private final static int THREAD_NUM = 5;
public static void main(String[] args){
for (int i = 0; i <THREAD_NUM; i++) {
new ExtendsThread("thread"+i).start();
}
}
public ExtendsThread(String name){
super(name);
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i < this.THREAD_NUM; i++) { System.out.println(this.getName()+i);
}
}
}
运行结果:
thread00
thread01
thread02
thread03
thread04
thread20
thread21
thread22
thread23
thread24
thread40
thread41
thread42
thread43
thread44
thread11
thread12
thread13
thread14
thread30
thread31
thread32
thread33
thread34
2.实现Runnable接口
public class ImplRunnable implements Runnable {
private static final int THREAD_NUM = 5;
@Override
public void run() {
for (int i = 0; i < THREAD_NUM; i++) {
System.out.println(Thread.currentThread().getName()+i);
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
for (int j = 0; j < THREAD_NUM; j++) {
ImplRunnable implRunnable= new ImplRunnable();
new Thread(implRunnable,"thread"+j).start();
}
}
}
运行结果
thread10
thread12
thread13
thread14
thread30
thread31
thread32
thread33
thread34
thread00
thread01
thread02
thread03
thread04
thread20
thread21
thread22
thread23
thread24
thread40
thread41
thread42
thread43
thread44
10.4试说明线程优先级及其调度的关系,并编写一个程序说明其关系。

处于就绪状态的线程首先进入就绪队列排队等候处理器资源,同一时刻在就绪队列中
的线程可能有多个,它们各自任务的轻重缓急程度不同。

为了体现上述差别,使工作得更加合理,多线程系统会给每个线程自动分配一个线程的优先级,任务较紧急重要的线程,其优先级就较高;相反则较低。

例如中断响应程序的线程一般都很紧急,优先级很高;而用来收集内存碎片的垃圾回收线程则不那么紧急,优先级较低。

在线程排队时,优先级高的线程可以排在较前的位置,能优先享用到处理器资源;而优先级较低的线程则只能等到排在它前面的高优先级线程执行完毕之后才能获得处理器资源,称之为抢先式调度。

对于优先极相同的线程,则遵循队列的“先到先服务”的原则,即先进入就绪状态排队的线程被优先分配到处理器资源,随后才为后进入队列的线程服务。

10.5为什么采用变量控制法来结束线程?
Stop()方法会导致错误发生、导致数据的不完整。

destroy()方法强制结束线程,但是这个方法在结束线程后,将不会释放锁。

10.6什么是线程的同步?线程同步的实现方法有几种?怎样实现?
当两个以上线程同时访问同一个变量,并且一个线程需要修改这个变量,如果不加以控制,将会带来访问数据不一致的问题.Java语言提供了专门机制以解决这种冲突,有效避免了同一个数据对象被多个线程同时访问。

(1)synchronized 方法
通过在方法声明中加入synchronized关键字来声明synchronized 方法。

synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。

(2)synchronized 块
通过 synchronized关键字来声明synchronized 块。

语法如下:
synchronized(syncObject) {
//允许访问控制的代码
}
synchronized 块的代码必须获得对象 syncObject 的锁方能执行,具体机制同前所述。

10.7什么是死锁?在多线程程序设计中如何防止死锁?
死锁问题是由于两个或多个线程无法得到相应的锁而造成的两个线程都等待的现象。

避免死锁的一个通用的经验法则是:决定获取锁的次序并始终遵照这个次序,按照与获取相反的次序释放锁。

10.8为什么要进行线程间的协作?
有时,当某一个线程进入同步方法后,共享变量并不满足它所需要的状态,该线程需要等待其他线程将共享变量改为它所需要的状态后才能往下执行。

由于此时其他线程无法进入临界区,所以就需要该线程放弃监控器,并返回到排队状态等待其他线程交回监控器。

10.9分析sleep()方法和yield()方法的区别,并通过编写一段程序来测试。

sleep()方法,可用于让线程沉睡若干毫秒。

它没有返回值,只接受线程沉睡时间,而且并不一定能够运行成功,当线程处在挂起状态时,由于某种原因被打断了,它会抛出一个类型为InterruptedException的异常。

yield() 为静态方法,功能是暂停当前正在执行的线程对象,并执行其他线程。

即它会暂停当前的线程,并将其放入可运行队列,而选同优先级的另一线程运行。

当然,如果没有相同优先级的可运行线程,yield()将什么也不做,继续让当前线程执行。

例:点击按钮后,每隔半秒程序发出一次“嘟”声。

import java.applet .*;
import java.awt.*;
import java.awt.event.*;
public class Example8 extends Applet implements ActionListener
{
Toolkit toolkit; Button button;
public void init()
toolkit=getToolkit(); //获得一个工具包对象
button=new Button("确定");
add(button);
button.addActionListener(this);
}
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == button)
{
for(int i=0; i<=9; i++)
{
toolkit.beep();
try {Thread.sleep(500);}
catch(InterruptedException e1){}
}
}
}
}
10.10对例10-4进行修改,实现订座系统的循环执行,而不是仅限于50个学生。

package threadDemo.thread;
public class Ex10_4_seatorderedCase {
private int seatResource; // 共享缓冲区
private boolean empty = true; // seatResource是否为空的信号量 public void setEmpty(){
empty=true;
public synchronized void push(int pubResource) {
while (!empty) { // 当缓冲区满的时候,等待
try { // 阻塞自己
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
seatResource = pubResource; // 将生成的座位号放到缓冲区
empty = false; // 设置缓冲区满状态
notify(); // 唤醒其他等待线程
}
public synchronized int pop() { // 从缓冲区订座位
while (empty) {
try {
wait(); // 当缓冲区空的时候,等待} catch (InterruptedException e) {
e.printStackTrace();
}
}
int popResource = seatResource;
seatResource = 0;
empty = true; // 设置缓冲区空状态
notify();
return popResource; // 返回所订座位号
public static void main(String[] args) {
Ex10_4_seatorderedCase so = new Ex10_4_seatorderedCase();
SeatProcedure sp = new SeatProcedure(so);
sp.start();
SeatConsumer sc = new SeatConsumer(so);
/*
*
* SeatConsumer 增加了一个add(),就是学生预定操作,就不是固定的学生了
*/
sc.add();
sc.add();
sc.start();
SeatRelease sr=new SeatRelease(so);
sr.start();
}
}
class SeatProcedure extends Thread { //生成空座位线程
private Ex10_4_seatorderedCase so;
public SeatProcedure(Ex10_4_seatorderedCase so) {
this.so = so;
}
public void run() {
for (int i = 1; i <= 30; i++) { //连续向缓冲区生成空座位号
int pubResource = i;
so.push(pubResource);
System.out.println("第" + pubResource + "号座位为空");
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}//class end
class SeatConsumer extends Thread{ //预订座位线程
private Ex10_4_seatorderedCase so;
private int studentnum=0;
public SeatConsumer(Ex10_4_seatorderedCase so) {
this.so= so;
}
public void add(){
studentnum++;
}
public void run() {
for (int i = 1; i <= studentnum; i++) {//50个学生连续从缓冲区取出座位号
synchronized (so) {
int sh = so.pop();
if (sh != 0) {
System.out.println("学生" + i + ""+"占了第"+ sh+"号座位");
} else {
System.out.println("没有空座,请等待!");
}
}
try {
sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}//class end
class SeatRelease extends Thread { //释放座位线程
private Ex10_4_seatorderedCase so;
public SeatRelease(Ex10_4_seatorderedCase so) {
this.so = so;
}
public void run() {
try {
sleep(20000);//20秒后
this.so.setEmpty();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 1; i <= 30; i++) { //从第一个开始,连续释放已预订的座位
int pubResource = i;
so.push(pubResource);
System.out.println("第" + pubResource + "号座位取消预订");
try {
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}。

相关文档
最新文档