模板方法模式,AQS源码
一.介绍
模板方法模式实际上就是相当于,将一些共有的方法和属性放在父类即抽象类里,然后将一些变化的方法,即可能形成多态特性的方法放在子类里。
1.先定义一个模板抽象类,在抽象类里定义一个通用的方法,即比较固定的方法,称为模板方法。
2.定义一些抽象的方法,具体给子类实现,在模板方法里调用这些抽象方法。形成一个固定的逻辑。
3.定义子类,具体去实现这些抽象方法。
二.UML图
三.代码
public abstract class AbstractTemplate { public void doBussiness(){ step1(); step2(); specialStep1(); specialStep2(); step3(); } protected void step1(){ System.out.println("第一步"); } protected void step2(){ System.out.println("第二步"); } protected void step3(){ System.out.println("第三步"); } protected abstract void specialStep1(); protected abstract void specialStep2(); }
public class ConcreteTemplate extends AbstractTemplate { @Override protected void specialStep1() { System.out.println("ConcreteTemplate"+"specialStep1"); } @Override protected void specialStep2() { System.out.println("ConcreteTemplate"+"specialStep2"); } }
public class ConcreteTemplate1 extends AbstractTemplate { @Override protected void specialStep1() { System.out.println("ConcreteTemplate1"+"specialStep1"); } @Override protected void specialStep2() { System.out.println("ConcreteTemplate1"+"specialStep2"); }
public class AppMain { public static void main(String[] args) { AbstractTemplate temp1 = new ConcreteTemplate(); temp1.doBussiness(); AbstractTemplate temp2 = new ConcreteTemplate1(); temp2.doBussiness(); } }
输出:
第一步
第二步
ConcreteTemplatespecialStep1
ConcreteTemplatespecialStep2
第三步
第一步
第二步
ConcreteTemplate1specialStep1
ConcreteTemplate1specialStep2
第三步
四:AQS里模板方法的运用
ReentrantLock内部使用了AQS来实现加锁释放锁功能,其中有公平锁和非公平锁。ReentrantLock内部有一个内部类Sync,这个类继承至AQS。AQS里的acquire方法就相当于一个模板方法,即排他获取资源的方法,里面调用了tryAcquire等未实现的虚方法。Sync类通过重写AQS里的方法来实现具体的线程同步逻辑。而非公平锁NonfairSync和公平锁FairSync都继承至Sync。Sync重写了AQS里的tryRelease方法,将公平锁和非公平锁统一,而公平锁和非公平锁的获取锁逻辑不同
所以在NonfairSync和FairSync内部实现了不同的具体的tryAcquire方法。
AbstractQueuedSynchronizer.java
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
ReentrantLock.java
public void lock() { sync.lock(); } public void unlock() { sync.release(1); }
ReentrantLock.Sync
abstract static class Sync extends AbstractQueuedSynchronizer { final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } protected final boolean tryRelease(int releases) { int c = getState() - releases; if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } }
ReentrantLock.FairSync
static final class FairSync extends Sync { final void lock() { acquire(1); } protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { 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; } }
ReentrantLock.FairSync
static final class NonfairSync extends Sync { final void lock() { if (compareAndSetState(0, 1)) setExclusiveOwnerThread(Thread.currentThread()); else acquire(1); } protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
五:总结
通过上面可以看出ReentrantLock调用lock方法加锁,这个lock方法实际上是调用的Sync类里的lock方法,而lock方法在NonfairSync和FairSync里被覆盖
lock方法里又调用了AQS的模板方法acquire, acquire里又调用了tryAcquire 方法,tryAcquire 方法在NonfairSync和FairSync分别被覆盖,从而实现了不同的获取锁逻辑。
Sync