修正Java中wait方法超时语意模糊性的一种方案(2)初步解决方案)
 
- UID
- 1066743
|

修正Java中wait方法超时语意模糊性的一种方案(2)初步解决方案)
初步解决方案我们的初步解决方案采用了Doug Lea(Doug Lea为对象并发领域世界级的专家)给出的一个显式的判断算法(关于该算法更加详细、深入的论述请参考参考文献〔1〕),通过该算法来辨别是否已经超时。采用该算法的解决方案的代码实现片断如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| class ActiveQueue {
...
public synchronized void enqueue(ClientRequest cr, long timeout)
throws InterruptedException, TimeoutException
{
if (isFull ()) { // 判断队列是否为满
long start = System.currentTimeMillis ();
long waitTime = timeout;
for (;;) { // 一直等待到队列不满被notify通知或者超时
wait (waitTime);
if (isFull ()) { //重新判断队列是否为满
long now = System.currentTimeMillis ();
long timeSoFar = now - start; // 队列仍然为满,计算已经等待的时间
if (timeSoFar >= msecTimeout) // 如果超时,抛出TimeoutException异常
throw new TimeoutException ();
else // 没有超时,计算还要等待的时间
waitTime = timeout - timeSoFar;
}
else // 被notify唤醒,并且队列不为满
break;
}
}
// 把用户请求添加到处理队列中
notifyAll();
}
...
}
|
可以看出,这个算法非常的简单,核心思路就是在每次wait返回时,计算wait等待的时间,并比较该时间和设定的要等待的时间,如果大于设定的要等待的时间,即确定为超时,否则确定为被notify唤醒。
使解决方案一般化上述的解决方案针对我们目前的要求已经可以很好的工作了,但是细心的读者一定会发现在上面给出的解决方案中我们把两个无关的概念揉合在了一起:队列是否为满的判断逻辑和是否超时的计算判断逻辑。为什么说这是两个无关的概念呢?因为队列是否为满是与我们开发的具体应用相关的,不同的应用会有不同类型的判断逻辑(比如:不使用队列的应用可能会有其他在概念上类似的判断逻辑),而计算判断超时的逻辑是和具体应用无关的。如果我们能够把这两个概念剥离开来,那么这二者就可以独立变化,我们的解决方案的可重用性就会增强。
我们使用Template Method模式(参见参考文献〔2〕)来指导我们的重构。首先,我们会根据和具体应用无关的超时计算判断的算法定义一个通用的算法框架,把和具体应用逻辑相关的条件判断作为一个抽象的hook方法,延迟到具体的应用中去实现,从而实现了和应用无关的超时计算判断逻辑的复用。实现该算法的抽象基类的关键实现代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| public abstract class WaitWithTiming
{
// wait方法要作用的对象,对于上述例子就是ActiveQueue
protected Object object_;
public WaitWithTiming (Object obj)
{
object_ = obj;
}
// 这是一个抽象的hook方法,由具体的应用实现,该方法由本算法框架调用
public abstract boolean condition ();
// 计算判断超时的算法框架实现
public final void timedWait (long timeout)
throws InterruptedException, TimeoutException
{
if (condition ()) { //调用具体应用实现的hook方法
long start = System.currentTimeMillis ();
long waitTime = msecTimeout;
for (;;) {
object_.wait (waitTime);
if (condition ()) {
long now = System.currentTimeMillis ();
long timeSoFar = now - start;
if (timeSoFar >= msecTimeout)
throw new TimeoutException ();
else
waitTime = timeout - timeSoFar;
}
else
break;
}
}
}
public final void announce() {
object_.notifyAll ();
}
}
|
|
|
|
|
|
|