ningendo

模板方法模式,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 

posted on 2020-12-12 01:37  Lunamonna  阅读(159)  评论(0编辑  收藏  举报

导航