当前位置:嗨网首页>书籍在线阅读

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() 方法中调用 semaphoreacquire() 方法来获取访问权限,该方法可能抛出 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();
}