练习题目
习题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();
}
}
}
运行结果如下。