以ReentrantLock和AQS的源码来分析设计模式之模板方法模式.

放弃该放弃的是无奈,放弃不该放弃的是无能,不放弃该放弃的是无知,不放弃不该放弃的是执着。

愿自己能在自己所热爱的道路上越走越远。


设计模式之模板方法模式.

设计模式之模板方法模式在JDK源码中体现的淋漓尽致, 所以说本文中就以ReentrantLockAQSJDK中的源码来体会模板方法模式.

模板方法模式就是入口调用的是父类的方法, 但是父类

1. ReentrantLock入口.

由于本文讨论的模板方法设计模式是基于ReentrantLock源码的, 所以讨论的开始时基于ReentrantLock的。

    public static void main(String[] args) throws Exception {
        
        // 以公平锁为例. 
        ReentrantLock lock = new ReentrantLock(true);
        // lock.lock()是加锁的入口. 
        lock.lock();

    }

我们知道在上面代码执行了lock.lock()之后, 其将会调用FairSyncLock方法. 我们来看看其源码.
注意: 重点来了.

    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;
        }
    }
设计模式之模板方法模式小结:
  1. 首先需要了解模板和方法:
    1. 模板: 模板就是整个功能实现体系中固定不变的. 就比如说AQS,模板就是acquire(), 并且该模板中依赖了’方法’, 并且该’方法’有一个固定的实现, 但是该固定的实现不做任何事情, 只是抛出一个异常,用来告诉程序员如果要实现该体系的功能必须实现当前方法.
    2. 方法: 方法就是整个功能实现体系中变动的方法, 只要实现该方法不同,那么这个功能的最终结果就不一样. 其实实现同一个功能, 不同程序员实现的不同方法将会对整个功能的结果就不一样.