需求来源
终止模式就是说,比如有一个代码逻辑,是会有多个线程来调用的,但是我们只能允许一个线程通过,别的线程只要发现有其他线程已经执行过这个方法那么就终止这个执行。
关键点
所以实现这种模式的关键点在于 如何知道别的线程已经执行过了,呃,那不就是那个变量留下痕迹不就行了, 所以需要一个共享变量来记录痕迹, 那么好了既然设计到共享变量那么就会有线程安全的问题,所以需要进行加锁,或者cas
示例,假设我们有一个服务,启动之后都会进行初始化
使用锁
/**
* 服务器
* @Author: puhaiguo
* @Date: 2022-07-10 19:36
* @Version 1.0
*/
public class Server {
private boolean flag = false;
public synchronized void start(){
if (flag){
return;
}
flag = true;
init();
}
private void init() {
System.out.println("进行初始化");
}
}
public class Test {
public static void main(String[] args) {
Server server = new Server();
for (int i = 0; i < 10; i++) {
new Thread(server::start).start();
}
}
}
cas
/**
* 服务器
* @Author: puhaiguo
* @Date: 2022-07-10 19:36
* @Version 1.0
*/
public class Server {
private volatile Boolean flag = false;
public void start(){
if (flag){
return;
}
/*开始进行cas尝试修改*/
Unsafe unsafe = MyJUCUtil.getUnsafe();
if (unsafe.compareAndSwapObject(this, getFlagAddr(), false, true)){
init();
}
}
private void init() {
System.out.println("进行初始化");
}
private long getFlagAddr(){
long addr = 0;
try {
Field flag = getClass().getDeclaredField("flag");
Unsafe unsafe = MyJUCUtil.getUnsafe();
addr = unsafe.objectFieldOffset(flag);
} catch (NoSuchFieldException e) {
e.printStackTrace();
}
return addr;
}
}
总结
终止模式 大概就是通过一个标记位,来控制线程执行逻辑