模板方法模式:
模板:
package com.atguigu.springcloud.template;
/**
* 抽象模板类Cook
* 步骤一:cookOne
* 步骤二:cookTwo
* 步骤三:cookThree
* 提供一个标准模板,执行顺序分别为一,二,三
*/
public abstract class Cook {
//抽象类的抽象方法没有方法体,类似于接口方法
public abstract void cookOne();
public abstract void cookTwo();
public abstract void cookThree();
/**
* 钩子函数
* 让子类决定cookTwo方法在模板中是否执行
*/
public boolean isTwo() {
return true;
}
/**
* 执行cook操作分别需要执行模板方法一,二,三
* 具体的三个方法由子类具体实现
* final修饰方法,此处则不允许重写
*/
final public void cook() {
cookOne();
if (isTwo()) {
cookTwo();
}
cookThree();
}
}
子类一:
package com.atguigu.springcloud.template.implement;
import com.atguigu.springcloud.template.Cook;
public class SmallCook extends Cook {
//此处定义false,则cook方法中不执行cookTwo()
private boolean isTwo = false;
@Override
public boolean isTwo() {
return isTwo;
}
@Override
public void cookOne() {
System.out.println("small执行步骤一");
}
@Override
public void cookTwo() {
System.out.println("small执行步骤二");
}
@Override
public void cookThree() {
System.out.println("small执行步骤三");
}
}
子类二:
package com.atguigu.springcloud.template.implement;
import com.atguigu.springcloud.template.Cook;
public class BigCook extends Cook {
//此处定义false,则cook方法中不执行cookTwo()
private boolean isTwo = true;
@Override
public boolean isTwo() {
return isTwo;
}
@Override
public void cookOne() {
System.out.println("Big执行步骤一");
}
@Override
public void cookTwo() {
System.out.println("Big执行步骤二");
}
@Override
public void cookThree() {
System.out.println("Big执行步骤三");
}
}
Test:
package com.atguigu;
import com.atguigu.springcloud.template.implement.BigCook;
import com.atguigu.springcloud.template.implement.SmallCook;
import org.junit.Test;
public class TemplateTest {
@Test
public void test() {
SmallCook smallCook = new SmallCook();
smallCook.cook();
BigCook bigCook = new BigCook();
bigCook.cook();
}
}
结果:
small执行步骤一
small执行步骤三
Big执行步骤一
Big执行步骤二
Big执行步骤三
AQS底层使用了模板方法模式:只需要继承AbstractQueuedSynchronizer类,并重写一部分方法
package com.atguigu.springcloud.util;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
/**
* 基于AQS自定义锁,实现互斥锁
* 典型的模板方法模式:
* 直接继承AbstractQueuedSynchronizer父类,子类实现具体的方法实现
*/
public class Sync extends AbstractQueuedSynchronizer {
/**
* tryAcquire方法是用来尝试获取独占资源
* compareAndSetState方法:state为0才设置为1,不可重入
* setExclusiveOwnerThread设置当前线程独占资源
*/
@Override
protected boolean tryAcquire(int arg) {
if (compareAndSetState(0, 1)) {
setExclusiveOwnerThread(Thread.currentThread());//互斥锁,共享锁
return true;
}
return false;
}
/**
* tryRelease方法是用来尝试释放资源
* 所以将state设置为0
*/
@Override
protected boolean tryRelease(int arg) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
/**
* 判断该线程是否独占资源
*/
@Override
protected boolean isHeldExclusively() {
return getState() == 1;
}
}
CLH队列(三位作者名称缩写):
CLH队列是FIFO(First Input First Output,先进先出)的双端双向队列,实现公平锁。线程通过AQS获取锁失败,就会将线程封装成一个Node节点,插入队列尾。当有线程释放锁时,后尝试把队头的next节点占用锁
AbstractQueuedSynchronizer类定义了名为Node的内部类,并在AbstractQueuedSynchronizer中已经实现了对线程队列的维护,所以自定义同步器只需要实现isHeldExclusively()等方法即可(上面的demo):
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
final boolean isShared() {
return nextWaiter == SHARED;
}
final Node predecessor() throws NullPointerException {
Node p = prev;
if (p == null)
throw new NullPointerException();
else
return p;
}
Node() {
}
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
Node(Thread thread, int waitStatus) {
this.waitStatus = waitStatus;
this.thread = thread;
}
}
AbstractQueuedSynchronizer类中的具体方法不再描述:
部分转自: