《疯狂Java讲义》第14章习题答案

练习题目

在这里插入图片描述

习题1

思路如下。
线程1:名为ThreadNum,用于打印1~52
线程2:名为ThreadChar,用于打印A~Z
用于共享的类:名为Print,有printNum,printChar方法。
答案如下。(自己写的,仅供参考)

该项目由Print.java, Demo1.java, ThreadNum.java, ThreadChar.java组成。

public class Print 
{
	//是否可以打印字母
	private boolean flag = false;
	public Print() {
		super();
	}

	synchronized int printNum(int num) {
		try
		{
			//可以打印字母
			if(flag) {
				wait();
			}
			else	//可以打印数字
			{
				System.out.print(++num);
				System.out.print(++num);
				flag = true;	//可以打印字母
				notifyAll();	//释放同步监视器的锁,唤醒其他线程
			}			
		}
		catch (InterruptedException ite)
		{
			ite.printStackTrace();
		}
		return num;
	}

	synchronized int printChar(int offset) {
		try
		{
			//不可以打印字母
			if(!flag) {
				wait();
			}
			else	//可以打印字母
			{
				char c = (char)('A' + offset);
				offset++;
				if(c == 'Z') {
					System.out.println(c);
				}
				else {
					System.out.print(c);
				}
				flag = false;	//不可用打印字母,可以打印数字
				notifyAll();	//释放同步监视器的锁,唤醒其他线程
			}			
		}
		catch (InterruptedException ite)
		{
			ite.printStackTrace();
		}
		return offset;
	}
}
public class ThreadChar extends Thread
{
	private Print p;
	private int offset = 0;

	public ThreadChar(String name,
		Print p) {
		super(name);
		this.p = p;
	}

	@Override
	public void run() {
		while(offset < 26) {
			offset = p.printChar(offset);
		}
	}	
}
public class ThreadNum extends Thread
{
	private Print p;
	private int num = 0;

	public ThreadNum(String name,
		Print p) {
		super(name);
		this.p = p;
	}

	@Override
	public void run() {
		while(num < 52) {
			num = p.printNum(num);
			
		}
	}	
}
public class Demo1 
{
	public static void main(String[] args) 
		throws InterruptedException {
		Print p = new Print();
		new ThreadNum("打印Num的线程", p).start();
		new ThreadChar("打印Char的线程", p).start();
	}
}

该项目的另一写法是:(仅修改Print.java)

import java.util.concurrent.locks.*;

public class Print 
{
	private final Lock lock = new ReentrantLock();
	private final Condition cond = lock.newCondition();
	//是否可以打印字母
	private boolean flag = false;
	public Print() {
		super();
	}

	int printNum(int num) {
		//加锁
		lock.lock();	  // block until condition holds
		try
		{
			//可以打印字母
			if(flag) {
				//Causes the current thread to wait until it is signalled or interrupted.
				cond.await();
			}
			else	//可以打印数字
			{
				System.out.print(++num);
				System.out.print(++num);
				flag = true;	//可以打印字母
				cond.signalAll();	//Wakes up all waiting threads.
			}			
		}
		catch (InterruptedException ite)
		{
			ite.printStackTrace();
		}
		finally {
			lock.unlock();
		}
		return num;
	}

	synchronized int printChar(int offset) {
		lock.lock();
		try
		{
			//不可以打印字母
			if(!flag) {
				//Causes the current thread to wait until it is signalled or interrupted.
				cond.await();
			}
			else	//可以打印字母
			{
				char c = (char)('A' + offset);
				offset++;
				if(c == 'Z') {
					System.out.println(c);
				}
				else {
					System.out.print(c);
				}
				flag = false;	//不可用打印字母,可以打印数字
				cond.signalAll();	//Wakes up all waiting threads.
			}			
		}
		catch (InterruptedException ite)
		{
			ite.printStackTrace();
		}
		finally {
			lock.unlock();
		}
		return offset;
	}
}

运行结果如下。
在这里插入图片描述

值得注意的是,并发访问Print时,比如ThreadChar创建的进程,这个进程执行printChar的次数不是(‘Z’-‘A’)次,而是大于(‘Z’-‘A’)次,因为,进程有可能执行下面的语句。

if(!flag) {
//Causes the current thread to wait until it is signalled or interrupted.
cond.await();
}

因此在ThreadNum和ThreadChar类中run方法的使用的是流程控制中的while语句。

习题2

该项目由Garage.java, Demo.java, ThreadCar.java组成。


public class Garage
{
	//表示车库,true可停车,false不可停车(已停车)
	private boolean[] garage = new boolean[]{true, true, true};

	private int available() {
		for(int i = 0; i < garage.length; i++) {
			if(garage[i] == true) {
				return i;
			}
		}
		return -1;
	}

	//@return i
	//成功返回车位号,失败返回-1
	public synchronized int park() {
		int i = -1;
		try
		{
			//无车位
			if((i = available()) < 0) {
				wait();	//等待车位空闲
			}
			else {
				garage[i] = false;	//已停车
				System.out.println(Thread.currentThread().getName() + ":"
					+ "在车位号" + i + "停车");
			}			
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}
		return i;	//返回车位号(0/1/2)
	}

	//成功返回true,失败返回false
	public synchronized boolean out(int id) {

		if(garage[id] == false) {
			garage[id] = true;	//可停车
			System.out.println(Thread.currentThread().getName() + ":"
					+ "在车位号" + id + "出库");
			notifyAll();
			return true;
		}
		else {
			return false;
		}
	}
}
public class Demo
{
	public static void main(String[] args) 
	{
		Garage g = new Garage();
		new ThreadCar("Car-0", g).start();
		new ThreadCar("Car-1", g).start();
		new ThreadCar("Car-2", g).start();
	}
}
public class ThreadCar extends Thread
{
	private Garage g;
	private int id = -1;
	private int count = 0;
	public  ThreadCar(String name, Garage g) {
		super(name);
		this.g = g;
	}

	@Override
	public void run() {
		try
		{
			while(count < 3) {
				//停车失败,继续停车
				while((id = g.park()) < 0);
				sleep(200);	//200ms
				//如果停车不成功,继续出库
				while(g.out(id) == false);
				count++;
			}	
		}
		catch (InterruptedException e)
		{
			e.printStackTrace();
		}

	}
}

运行结果如下。
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值