05-案例实现
案例实现
根据如下步骤实现本案例。
1.创建一个类 PrintQueue
,用于实现打印队列:
public class PrintQueue {
2.该类包含3个私有属性:一个命名为 semaphore
的信号量、一个命名为 freePrinters
的布尔类型数组,以及一个命名为 lockPrinters
的锁。代码如下:
private final Semaphore semaphore;
private final boolean freePrinters[];
private final Lock lockPrinters;
3.实现类的构造方法。在构造方法中初始化这3个属性,代码如下:
public PrintQueue(){
semaphore=new Semaphore(3);
freePrinters=new boolean[3];
for (int i=0; i<3; i++){
freePrinters[i]=true;
}
lockPrinters=new ReentrantLock();
}
4.实现 printJob()
方法。该方法接收一个 Object
类型的参数 document
,以用来模拟文档打印功能:
public void printJob (Object document){
5.首先,在 printJob()
方法中调用 semaphore
的 acquire()
方法来获取访问权限,该方法可能抛出 InterruptedException
异常,因此需要进行异常处理:
try {
semaphore.acquire();
6.调用私有的 getPrinter()
方法,用于获取执行当前打印任务的打印机的编号:
int assignedPrinter=getPrinter();
7.然后模拟文档的打印,随机等待一段时间:
long duration=(long)(Math.random()*10);
System.out.printf("%s - %s: PrintQueue: Printing a Job in
Printer %d during %d seconds\n",
new Date(), Thread.currentThread().getName(),
assignedPrinter,duration);
TimeUnit.SECONDS.sleep(duration);
8.最后,调用 semaphore
对象的 release()
方法释放信号量,并通过把 freePrinters
数组中对应索引的值设置为 true
,将打印机标记为空闲状态:
freePrinters[assignedPrinter]=true;
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
9.实现 getPrinter()
方法。该方法为私有方法,返回值为 int
类型,没有任何参数:
private int getPrinter() {
10.定义一个 int
类型的变量,用于保存打印机编号:
int ret = -1;
11.获取对 lockPrinters
对象的访问权限:
try {
lockPrinters.lock();
12.遍历 freePrinters
数组,找到其中的第一个 true
值,并将其编号保存到 ret
变量中。将该值修改为 false
,因为它对应的打印机将进入忙碌状态:
for (int i=0; i<freePrinters.length; i++) {
if (freePrinters[i]){
ret=i;
freePrinters[i]=false;
break;
}
}
13.释放 lockPrinters
对象,并返回选中的打印机编号:
} catch (Exception e) {
e.printStackTrace();
} finally {
lockPrinters.unlock();
}
return ret;
14.创建 Job
类并实现 Runnable
接口。这个类实现了向打印机发送打印任务的功能:
public class Job implements Runnable {
15.声明一个 PrintQueue
类型的属性,将其命名为 printQueue
:
private PrintQueue printQueue;
16.实现该类的构造器。在构造器中初始化 printQueue
:
public Job(PrintQueue printQueue){
this.printQueue=printQueue;
}
17.实现 run()
方法:
@Override
public void run() {
18.在该方法开始时,向控制台打印一条消息,用来表明该任务开始执行:
System.out.printf("%s: Going to print a job\n",
Thread.currentThread().getName());
19.调用 printQueue
对象的 printJob()
方法:
printQueue.printJob(new Object());
20.同样,在方法结束时,向控制台打印一条消息,用来表明该任务已经执行结束:
System.out.printf("%s: The document has been printed\n",
Thread.currentThread().getName());
}
21.通过生成 Main
类和实现其 main()
方法来实现该案例的主类:
public class Main {
public static void main (String args[]){
22.创建一个 PrintQueue
类型的局部变量 printQueue
:
PrintQueue printQueue=new PrintQueue();
23.创建12个线程。每个线程都会执行一个 Job
对象,用来向打印机队列发送打印任务:
Thread[] threads=new Thread[12];
for (int i=0; i < threads.length i++){
thread[i]=new Thread(new Job(printQueue),"Thread"+i);
}
24.启动这12个线程:
for (int i=0; i < threads.length; i++){
thread[i].start();
}