16
17 if (nextProbablePrime.longValue() >= upperBound)
18
19 result = null;
20
21 else result = nextProbablePrime;
22
23 return result;
24
25 }
现在已经定义了建立该解决方案的公共接口和工具,你现在可以对该任务进行细化了。我们将首先定义线程门的实现,它指定控制访问结果缓冲器的方式。
线程门实现
线程门的目标是确保多个阅读器可以访问素数缓冲器,而且无需阻挡搜索线程对其增加结果。
一个阅读器线程应该能够无需等待就可以访问任何可用结果;但是如果没有结果可用,它必须排队等待,直到至少有一个结果可用。该示例应用使用了一个公平设计原则,因此结果大致按照线程到达的顺序来被提供。这个示例应用的重点不是按照严格队列顺序分发结果;而是在一定时间间隔内请求素数的线程,在下一批线程到来之前都能够都获得它们的数据。
现实世界中能够说明这种设计理念的类似事物是咖啡店情况。为了让顾客满意,在黄金时段咖啡订单是“批量处理”的。服务员取走客户订单后,将选择相同品种咖啡的用户分成一组,由咖啡机分批来制作咖啡,这样该组客户基本上可以同时享用上自己的咖啡;然后咖啡机再制作下一批客户的咖啡,按照如此过程进行重复。按照这种设计方案,在指定时间间隔内进入咖啡制作排队顺序的客户可以同时得到自己咖啡,当然可能不会严格安装下单的顺序来被提供咖啡。设想一下,如果咖啡机每次只准备一杯咖啡,其效率会有多么低下。
回到产生和缓冲素数的任务中,通过一个具有类似二进制锁功能的门,这个简单的应用程序能够控制对结果缓冲器的访问:当这个门打开时,线程可以通过,当它被关闭时,线程必须排队等候直到其被重新打开。在某种意义上来说它比一个门锁更智能,它可以将等待线程进行批处理,可以确保同一批中的所有线程能够同时通过这个门;较早一批线程要比较晚一批线程的优先级高。门实现有其创新性的特点,即无论有多少线程在等待,结果总可以被写入到结果缓冲器中。如果以一个交通信号灯做比喻,那么线程门类可能更像一个铁路交叉口信号灯,火车总可以获得优先通行权。
在com.javaworld.primefinder.ThreadGate中包含了门实现的过程,如列表3所示。
列表3.门实现
1 package com.javaworld.primefinder;
2
3 class ThreadGate
4
5 {
6
7 private int waitPosition;
8
9 private int generationSize;
10
11 private int openAttempts;
12
13 private int activeSearchThreads;
14
15 private boolean open;
16
17 public ThreadGate(int searchThre