放弃该放弃的是无奈,放弃不该放弃的是无能,不放弃该放弃的是无知,不放弃不该放弃的是执着。
愿自己能在自己所热爱的道路上越走越远。
设计模式之模板方法模式.
设计模式之模板方法模式在JDK源码中体现的淋漓尽致, 所以说本文中就以
ReentrantLock和AQSJDK中的源码来体会模板方法模式.
模板方法模式就是入口调用的是父类的方法, 但是父类
1. ReentrantLock入口.
由于本文讨论的模板方法设计模式是基于ReentrantLock源码的, 所以讨论的开始时基于ReentrantLock的。
public static void main(String[] args) throws Exception {
// 以公平锁为例.
ReentrantLock lock = new ReentrantLock(true);
// lock.lock()是加锁的入口.
lock.lock();
}
我们知道在上面代码执行了lock.lock()之后, 其将会调用FairSync的Lock方法. 我们来看看其源码.
注意: 重点来了.
final void lock() {
// 通过观察FairSync以及Sync发现,acquire(1)是其父类AQS中的方法.
// 好接下来我们来看看AQS中的acquire方法.
acquire(1);
}
acquire()方法体.
public final void acquire(int arg) {
// 1. 首先说明下, 这里是不会讲解AQS源码的, 只是分析AQS中的模板设计模式, 如果要看AQS源码分析,请移步JUC模板下查看.
// 2. 注意, 这里的tryAcquire()在AQS中有一个默认的实现,但是其中就只是抛出了一个异常, 没有起任何效果在实现锁的情况下.
// 3. 所以这里的tryAcquire() 就是FairSync实现的tryAcquire.
// 4. 接下来我们看看FairSync中的tryAcquire方法.
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
FairSync中的tryAcquire方法.
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 1. 好了重点又来了.并且是模板方法设计模式的核心.
// 2. 这里(AQS)的子类, 又调用了父类的hasQueuedPredecessors()方法.
// 3. 好了, 模板方法设计模式在JDK源码中已经解释清楚了. 下文将会对此进行总结.
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
设计模式之模板方法模式小结:
- 首先需要了解模板和方法:
- 模板: 模板就是整个功能实现体系中固定不变的. 就比如说AQS,模板就是
acquire(), 并且该模板中依赖了’方法’, 并且该’方法’有一个固定的实现, 但是该固定的实现不做任何事情, 只是抛出一个异常,用来告诉程序员如果要实现该体系的功能必须实现当前方法. - 方法: 方法就是整个功能实现体系中变动的方法, 只要实现该方法不同,那么这个功能的最终结果就不一样. 其实实现同一个功能, 不同程序员实现的不同方法将会对整个功能的结果就不一样.
- 模板: 模板就是整个功能实现体系中固定不变的. 就比如说AQS,模板就是