常用程序模式-LifeCycle模式

常用程序模式-LifeCycle模式

场景

当我们要监控一个组件的生命周期的时候,比如,启动时,启动后,关闭前,关闭后

实现

LifeCycleModule
public interface LifeCycleModule {/*** 获取当前状态* @return*/LifeCycle.State getCurrentState();/*** add listener* @param listener*/void addListener(LifeCycleListener listener);/*** 启动*/void start();/*** 停止*/void stop();/*** 关闭*/void close();
}

AbstractLifeCycleModule:

public abstract class AbstractLifeCycleModule implements LifeCycleModule {private LifeCycle lifeCycle = new LifeCycle();private List<LifeCycleListener> listeners = new ArrayList<>();@Overridepublic LifeCycle.State getCurrentState() {return lifeCycle.getState();}@Overridepublic void addListener(LifeCycleListener listener) {listeners.add(listener);}@Overridepublic void start() {synchronized (lifeCycle){if (!lifeCycle.canChangeToStart()){return;}for (LifeCycleListener listener : listeners) {listener.beforeStart();}doStart();lifeCycle.changeToStarted();for (LifeCycleListener listener : listeners) {listener.afterStart();}}}protected abstract void doStart();@Overridepublic void stop() {synchronized (lifeCycle){if (!lifeCycle.canChangeToStop()){return;}for (LifeCycleListener listener : listeners) {listener.beforeStop();}doStop();lifeCycle.changeToStop();for (LifeCycleListener listener : listeners) {listener.afterSop();}}}protected abstract void doStop();@Overridepublic void close() {synchronized (lifeCycle){if (!lifeCycle.canChangeToClose()){return;}for (LifeCycleListener listener : listeners) {listener.beforeClose();}lifeCycle.changeToClosed();try {doClose();}catch (Exception e){throw new RuntimeException(e);}finally {for (LifeCycleListener listener : listeners) {listener.afterClose();}}}}protected abstract void doClose();
}
LifeCycleListener
public interface LifeCycleListener {/*** 在开始之前*/void beforeStart();/*** 在开始之后*/void afterStart();/*** 在停止之前*/void beforeStop();/*** 在停止之后*/void afterSop();/*** 在关闭之前*/void beforeClose();/*** 在关闭之后*/void afterClose();
}
LifeCycle 状态管理
public class LifeCycle {private volatile LifeCycle.State state = State.INIT;public LifeCycle.State getState() {return state;}public boolean canChangeToStart() {State curState = this.state;if (curState == State.INIT || curState == State.STOP) {return true;}if (curState == State.START) {return false;}if (curState == State.CLOSE) {throw new IllegalArgumentException("can not move close to start");}throw new IllegalArgumentException("illegal state");}public synchronized boolean changeToStarted() {State curState = this.state;if (curState == State.INIT || curState == State.STOP) {state = State.START;return true;}return false;}public boolean canChangeToClose() {State curState = this.state;if (curState == State.CLOSE) {return false;}return true;}public synchronized boolean changeToClosed() {State curState = this.state;if (curState == State.CLOSE) {return false;}state = State.CLOSE;return true;}public boolean canChangeToStop() {State curState = this.state;if (curState == State.START) {return true;}return false;}public synchronized boolean changeToStop() {State curState = this.state;if (curState == State.START) {state = State.STOP;return true;}return false;}enum State {INIT, START, STOP, CLOSE}public boolean initialized() {return this.state == State.INIT;}public boolean started() {return this.state == State.START;}public boolean stopped() {return this.state == State.STOP;}public boolean closed() {return this.state == State.CLOSE;}}

测试

@Slf4j
public class WebServer extends AbstractLifeCycleModule{public WebServer(){addListener(new WebServerListener());}@Overrideprotected void doStart() {log.info("{} doStart", Thread.currentThread().getName());}@Overrideprotected void doStop() {log.info("{} doStop", Thread.currentThread().getName());}@Overrideprotected void doClose() {log.info("{} doClose", Thread.currentThread().getName());}static class WebServerListener implements LifeCycleListener{@Overridepublic void beforeClose() {log.info("{} before close", Thread.currentThread().getName());}@Overridepublic void afterClose() {log.info("{} after close", Thread.currentThread().getName());}@Overridepublic void beforeStart() {log.info("{} before start", Thread.currentThread().getName());}@Overridepublic void afterStart() {log.info("{} after start", Thread.currentThread().getName());}@Overridepublic void beforeStop() {log.info("{} before stop", Thread.currentThread().getName());}@Overridepublic void afterSop() {log.info("{} after stop", Thread.currentThread().getName());}}public static void main(String[] args) throws InterruptedException {WebServer webServer = new WebServer();webServer.start();TimeUnit.SECONDS.sleep(1);webServer.stop();TimeUnit.SECONDS.sleep(1);webServer.close();}
}

结果:

INFO com.example.lifecycle.WebServer -- main before start
INFO com.example.lifecycle.WebServer -- main doStart
INFO com.example.lifecycle.WebServer -- main after start
INFO com.example.lifecycle.WebServer -- main before stop
INFO com.example.lifecycle.WebServer -- main doStop
INFO com.example.lifecycle.WebServer -- main after stop
INFO com.example.lifecycle.WebServer -- main before close
INFO com.example.lifecycle.WebServer -- main doClose
INFO com.example.lifecycle.WebServer -- main after close

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/657704.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring-web搭建

目录 1&#xff1a;spring-web是什么原理以及组成 2&#xff1a;spring-web的搭建&#xff08;以普通tomcat服务器做基础&#xff09; 1->环境&#xff08;自己去建一个普通web项目&#xff09; 2->WEB-INF的web.xml配置&#xff08;程序入口&#xff09; 3->comm…

Qt6入门教程 14:QToolButton

目录 一.简介 二.常用接口 1.void setMenu(QMenu * menu) 2.void setPopupMode(ToolButtonPopupMode mode) 3.void setToolButtonStyle(Qt::ToolButtonStyle style) 4.void setArrowType(Qt::ArrowType type) 5.void setDefaultAction(QAction * action) 三.实战演练 1…

k8s从私有库harbor中拉取镜像

一、前言 Docker镜像是构建应用程序的基础。然而&#xff0c;许多组织和开发团队希望保留他们的Docker镜像在私有仓库中&#xff0c;并从中拉取镜像&#xff0c;而不是从公共Docker Hub中下载。这样做的原因有很多&#xff0c;包括&#xff1a; 1. 安全性&#xff1a;私有仓库可…

C++ //练习 3.13 下列的vector对象各包含多少个元素?这些元素的值分别是多少?

C Primer&#xff08;第5版&#xff09; 练习 3.13 练习 3.13 下列的vector对象各包含多少个元素&#xff1f;这些元素的值分别是多少&#xff1f; ( a ) vector<int> v1; ( b ) vector<int> v2(10); ( c ) vector<int> v3(10, 42); ( d ) vector<in…

通过MediaStore查询image,video,arm,pdf等等文件数据

需要直接查询系统库来获取手机上的全部文件信息&#xff0c;如&#xff1a;图片&#xff0c;视频&#xff0c;音频&#xff0c;pdf文件等等。 直接上代码&#xff0c;获取文件的方法&#xff1a; SuppressLint("Range") public ArrayList<DataBean> getFiles(…

collection、ofType、select的联合用法(Mybatis实现树状结构查询)

需求 得到树结构数据也可以用lambda表达式也行&#xff0c;也可以直接循环递归也行&#xff0c;本文采用的是直接在Mybatis层得到结果&#xff0c;各有各的优势。 代码 1、实体类 Data public class CourseChapterVO implements Serializable {private static final long s…

Java 字符串 07 练习-手机号屏蔽、身份证号信息查看,游戏骂人敏感词替换

注意点&#xff1a;只有返回值才是被截取的小串&#xff0c;所以需要有一个变量去承接它&#xff1b; 自己写的代码&#xff1a; import java.util.Scanner; public class practice {public static void main(String[] args) {Scanner input new Scanner(System.in);String …

Zookeeper分布式命名服务实战

目录 分布式命名服务 分布式API目录 分布式节点的命名 分布式的ID生成器 分布式的ID生成器方案&#xff1a; 基于Zookeeper实现分布式ID生成器 基于Zookeeper实现SnowFlakeID算法 分布式命名服务 命名服务是为系统中的资源提供标识能力。ZooKeeper的命名服务主要是利用Z…

ThreadLocal作用实例

ThreadLocal ThreadLocal表示线程的“局部变量”&#xff0c;它确保每个线程的ThreadLocal变量都是各自独立的&#xff0c;它提供了一种方法来创建只能被当前线程访问的变量。这意味着如果有两个不同的线程访问同一个ThreadLocal变量&#xff0c;那么这两个线程将不能看到彼此…

【issue-halcon例程学习】lines_gauss.hdev

例程功能 代码如下 dev_close_window () read_image (Angio, angio-part) get_image_size (Angio, Width, Height) dev_open_window (0, 0, 3 * Width / 2, 3 * Height / 2, black, WindowID) dev_display (Angio) dev_set_color (blue) MaxLineWidth : 8 Contrast : 12 calc…

Java中的线程安全

关于多线程并发环境下&#xff0c;数据的安全问题。 1.为什么这个是重点&#xff1f; 以后在开发中&#xff0c;我们的项目都是运行在服务器当中&#xff0c;而服务器已经将线程的定义&#xff0c;线程对象的创建&#xff0c;线程的启动等&#xff0c;都已经实现完了。这些代码…

QT自制软键盘 最完美、最简单、支持中文输入(二)

目录 一、前言 二、本自制虚拟键盘特点 三、中文输入原理 四、组合键输入 五、键盘事件模拟 六、界面 七、代码 7.1 frmKeyBoard 头文件代码 7.2 frmKeyBoard 源文件代码 八、使用示例 九、效果 十、结语 一、前言 由于系统自带虚拟键盘不一定好用&#xff0c;也不一…

【python】合理使用copy与deepcopy

合理使用**copy**与**deepcopy**对于dict和list等数据结构的对象&#xff0c;直接赋值使用的是引用的方式。而有些情况下需要复制整个对象&#xff0c;这时可以使用copy包里的copy和deepcopy&#xff0c;这两个函数的不同之处在于后者是递归复制的。效率也不一样&#xff1a;&a…

动态设置小程序IOS底部小黑条

创建setIOSAreaMixin.js文件 import {mapState,mapMutations } from vuexexport default {computed: {...mapState("ios_area", ["globalAreaClass", isSafeAreaCalculated])},mounted() {if (!this.isSafeAreaCalculated) {this.calculateSafeAreaClass(…

牛客网-----------[NOIP2006]数列

题目描述 给定一个正整数k(3≤k≤15),把所有k的方幂及所有有限个互不相等的k的方幂之和构成一个递增的序列&#xff0c;例如&#xff0c;当k3时&#xff0c;这个序列是&#xff1a; 1&#xff0c;3&#xff0c;4&#xff0c;9&#xff0c;10&#xff0c;12&#xff0c;13&…

2024年重庆市公务员考试报名明天开始,招聘4530人!

2024年重庆公务员招录公告已出&#xff0c;招聘人数&#xff1a;4530人 ✅重庆市考重要时间节点 报名时间&#xff1a;2月1日9:00-2月6日9:00 缴费时间&#xff1a;2月8日 笔试时间&#xff1a;3月16日-17日 笔试查成绩时间&#xff1a;4月15日 面试时间&#xff1a;4月27日-2…

C++文件操作(1)

C文件操作 1.文本的写入及读取文本文件写入文本文件读取 2.二进制文件的写入及读取二进制文件写入二进制文件读取 3.小结 C也有处理文件的能力&#xff0c;其功能实现依赖文件流。文件流是C中用来处理文件输入输出的一种流类。文件流可以用于从文件中读取数据或将数据写入到文件…

《游戏-03_2D-开发》

基于《游戏-02_2D-开发》&#xff0c; 继续制作游戏&#xff1a; 首先要做的时切割人物Idle空闲状态下的动画&#xff0c; 在切割之前我们需要创建一个文件夹&#xff0c;用来存放动画控制器AnimatorContoller&#xff0c; 再创建一个人物控制器文件夹用来存放人物控制器&…

【Ubuntu 22.04.3 LTS】apt-get下载安装有关问题可能原因及解决方法

ubuntu 22.04.3 LTS unaccountably error 装啥啥没依赖 可能是用了不合适的源&#xff0c;换个就好了 Now, let’s take a look at the lsb_release output, with a special focus on the Codename, which could be a crucial piece of information. The lsb_release comm…

认识BPMN2.0

&#x1f496;专栏简介 ✔️本专栏将从Camunda(卡蒙达) 7中的关键概念到实现中国式工作流相关功能。 ✔️文章中只包含演示核心代码及测试数据&#xff0c;完整代码可查看作者的开源项目snail-camunda ✔️请给snail-camunda 点颗星吧&#x1f618; &#x1f496;说在前面 …