《瘋狂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();
		}

	}
}

運行結果如下。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章