模板方法模式,AQS源码

一.介绍

  模板方法模式实际上就是相当于,将一些共有的方法和属性放在父类即抽象类里,然后将一些变化的方法,即可能形成多态特性的方法放在子类里。

       1.先定义一个模板抽象类,在抽象类里定义一个通用的方法,即比较固定的方法,称为模板方法。

  2.定义一些抽象的方法,具体给子类实现,在模板方法里调用这些抽象方法。形成一个固定的逻辑。

  3.定义子类,具体去实现这些抽象方法。

 

二.UML图

模板方法模式,AQS源码

 

 

 

三.代码

 

publicabstractclass AbstractTemplate {

publicvoid doBussiness(){

step1();

step2();

specialStep1();

specialStep2();

step3();

}

protectedvoid step1(){

System.out.println("第一步");

}

protectedvoid step2(){

System.out.println("第二步");

}

protectedvoid step3(){

System.out.println("第三步");

}

protectedabstractvoid specialStep1();

protectedabstractvoid specialStep2();

}

 

publicclass ConcreteTemplate extends AbstractTemplate {

@Override

protectedvoid specialStep1() {

System.out.println("ConcreteTemplate"+"specialStep1");

}

@Override

protectedvoid specialStep2() {

System.out.println("ConcreteTemplate"+"specialStep2");

}

}

publicclass ConcreteTemplate1 extends AbstractTemplate {

@Override

protectedvoid specialStep1() {

System.out.println("ConcreteTemplate1"+"specialStep1");

}

@Override

protectedvoid specialStep2() {

System.out.println("ConcreteTemplate1"+"specialStep2");

}

publicclass AppMain {

publicstaticvoid 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方法。

模板方法模式,AQS源码

 

 

 模板方法模式,AQS源码

 

 

 AbstractQueuedSynchronizer.java

publicfinalvoid acquire(int arg) {

if (!tryAcquire(arg) &&

acquireQueued(addWaiter(Node.EXCLUSIVE), arg))

selfInterrupt();

}

ReentrantLock.java

publicvoid lock() {

sync.lock();

}

publicvoid unlock() {

sync.release(1);

}

ReentrantLock.Sync 

abstractstaticclass Sync extends AbstractQueuedSynchronizer {

finalboolean nonfairTryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

returntrue;

}

}

elseif (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc < 0) // overflow

thrownew Error("Maximum lock count exceeded");

setState(nextc);

returntrue;

}

returnfalse;

}

protectedfinalboolean tryRelease(int releases) {

int c = getState() - releases;

if (Thread.currentThread() != getExclusiveOwnerThread())

thrownew IllegalMonitorStateException();

boolean free = false;

if (c == 0) {

free = true;

setExclusiveOwnerThread(null);

}

setState(c);

return free;

}

}

ReentrantLock.FairSync 

staticfinalclass FairSync extends Sync {

finalvoid lock() {

acquire(1);

}

protectedfinalboolean tryAcquire(int acquires) {

final Thread current = Thread.currentThread();

int c = getState();

if (c == 0) {

if (!hasQueuedPredecessors() &&

compareAndSetState(0, acquires)) {

setExclusiveOwnerThread(current);

returntrue;

}

}

elseif (current == getExclusiveOwnerThread()) {

int nextc = c + acquires;

if (nextc < 0)

thrownew Error("Maximum lock count exceeded");

setState(nextc);

returntrue;

}

returnfalse;

}

}

ReentrantLock.FairSync 

staticfinalclass NonfairSync extends Sync {

finalvoid lock() {

if (compareAndSetState(0, 1))

setExclusiveOwnerThread(Thread.currentThread());

else

acquire(1);

}

protectedfinalboolean tryAcquire(int acquires) {

return nonfairTryAcquire(acquires);

}

}

 

五:总结

  通过上面可以看出ReentrantLock调用lock方法加锁,这个lock方法实际上是调用的Sync类里的lock方法,而lock方法在NonfairSync和FairSync里被覆盖

lock方法里又调用了AQS的模板方法acquire, acquire里又调用了tryAcquire 方法,tryAcquire 方法在NonfairSync和FairSync分别被覆盖,从而实现了不同的获取锁逻辑。

 

 

 

 

Sync 

以上是 模板方法模式,AQS源码 的全部内容, 来源链接: utcz.com/a/74964.html

回到顶部