文章目录 演示代码 本地缓存数据存入文件 从文件提取数据到本地缓存 工具类 实战 初始化操作 执行 本地缓存数据存入文件 的线程任务 持久化工具类
演示代码
本地缓存数据存入文件
public static void testQ15 ( ) { LinkedBlockingDeque < ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > > failureStatusCache = new LinkedBlockingDeque < > ( 4 ) ; LinkedBlockingDeque < ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > > successStatusCache = new LinkedBlockingDeque < > ( 4 ) ; LinkedBlockingDeque < ConcurrentHashMap < String , Integer > > pushedStateCache = new LinkedBlockingDeque < > ( 4 ) ; ObjectOutputStream oos = null ; ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > mapF = new ConcurrentHashMap < > ( ) ; mapF. put ( "失败数据" , new ConcurrentHashMap < Integer , Integer > ( ) { { put ( 1 , 0 ) ; } } ) ; failureStatusCache. add ( mapF) ; ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > mapS = new ConcurrentHashMap < > ( ) ; mapS. put ( "成功数据" , new ConcurrentHashMap < Integer , Integer > ( ) { { put ( 2 , 0 ) ; } } ) ; successStatusCache. add ( mapS) ; pushedStateCache. add ( new ConcurrentHashMap < String , Integer > ( ) { { put ( "哈哈哈" , 3 ) ; } } ) ; log. info ( "【SoulCache - saveData】持久化数据到文件" ) ; try { oos = new ObjectOutputStream ( Files . newOutputStream ( Paths . get ( PersistencePath . createFile ( "tzh" ) ) ) ) ; oos. writeObject ( failureStatusCache) ; oos. writeObject ( successStatusCache) ; oos. writeObject ( pushedStateCache) ; log. info ( "【SoulCache - saveData】持久化数据到文件 | 结束" ) ; } catch ( Exception e) { log. error ( "保存持久化文件异常" , e) ; } finally { try { if ( oos != null ) { oos. close ( ) ; } } catch ( IOException ioe) { log. error ( "IO流关闭异常" , ioe) ; } } }
从文件提取数据到本地缓存
public static void testQ16 ( ) { ObjectInputStream ois = null ; try { String path = PersistencePath . getPath ( "tzh" ) ; log. info ( "【SoulCache - loadData】加载到内存开始... | path:{}" , path) ; ois = new ObjectInputStream ( Files . newInputStream ( Paths . get ( path) ) ) ; LinkedBlockingDeque < ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > > failureStatusCache = ( LinkedBlockingDeque < ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > > ) ois. readObject ( ) ; LinkedBlockingDeque < ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > > successStatusCache = ( LinkedBlockingDeque < ConcurrentHashMap < String , ConcurrentHashMap < Integer , Integer > > > ) ois. readObject ( ) ; LinkedBlockingDeque < ConcurrentHashMap < String , Integer > > pushedStateCache = ( LinkedBlockingDeque < ConcurrentHashMap < String , Integer > > ) ois. readObject ( ) ; System . out. println ( "失败数据:" + failureStatusCache. getFirst ( ) . toString ( ) ) ; System . out. println ( "成功数据:" + successStatusCache. getFirst ( ) . toString ( ) ) ; System . out. println ( pushedStateCache. getFirst ( ) . toString ( ) ) ; log. info ( "【SoulCache - loadData】加载到内存 结束" ) ; } catch ( Exception e) { log. error ( "加载内存持久化文件异常" , e) ; } finally { try { if ( ois != null ) { ois. close ( ) ; } PersistencePath . delFile ( "tzh" ) ; } catch ( IOException ioe) { log. error ( "IO流关闭异常" , ioe) ; } } }
工具类
public class PersistencePath { private static final Logger logger = LoggerFactory . getLogger ( PersistencePath . class ) ; private static AtomicInteger aofVersion = new AtomicInteger ( 0 ) ; private final static String path = "/Users/zeki/test/" ; public static String serverId= "1" ; public static String serverName= "titan" ; private static String getAofVersion ( ) { String _v = DateUtil . formatDateyyyyMMddHHmmss ( System . currentTimeMillis ( ) ) + "_" + aofVersion. get ( ) ; aofVersion. incrementAndGet ( ) ; return _v; } private static String buildFileName ( ) { return String . format ( "%s%s.obj" , Optional . ofNullable ( serverName) . orElse ( defaultServerName ( ) ) , serverId) ; } private static String buildFileName_AOF ( ) { return buildFileName ( ) . concat ( getAofVersion ( ) ) ; } private static String buildFileName ( String prefixName) { return String . format ( "%s%s_%s.obj" , Optional . ofNullable ( serverName) . orElse ( defaultServerName ( ) ) , serverId, prefixName) ; } public static String getPath ( ) { String fileName = buildFileName ( ) ; File file = new File ( path, fileName) ; if ( file. exists ( ) ) { return path + fileName; } logger. warn ( "getPath {}{} 不存在" , path, fileName) ; return null ; } public static String getPath_AOF ( ) { String fileName = buildFileName_AOF ( ) ; File file = new File ( path, fileName) ; if ( file. exists ( ) ) { return path + fileName; } return null ; } public static String getPath ( String prefixName) { String fileName = buildFileName ( prefixName) ; File file = new File ( path, fileName) ; if ( file. exists ( ) ) { return path + fileName; } return null ; } public static String createFile ( ) throws IOException { String fileName = buildFileName ( ) ; File file = new File ( path, fileName) ; if ( ! file. exists ( ) ) { file. createNewFile ( ) ; } return path + fileName; } public static String createFile_AOF ( ) throws IOException { String fileName = buildFileName_AOF ( ) ; File file = new File ( path, fileName) ; if ( ! file. exists ( ) ) { file. createNewFile ( ) ; } return path + fileName; } public static String createFile ( String prefixName) throws IOException { String fileName = buildFileName ( prefixName) ; File file = new File ( path, fileName) ; if ( ! file. exists ( ) ) { file. createNewFile ( ) ; } return path + fileName; } public static boolean delFile ( ) { String fileName = buildFileName ( ) ; File file = new File ( path, fileName) ; if ( file. exists ( ) ) { return file. delete ( ) ; } return false ; } public static boolean delFile ( String prefixName) { String fileName = buildFileName ( prefixName) ; File file = new File ( path, fileName) ; if ( file. exists ( ) ) { FileUtil . rename ( file, String . format ( "%s_bak_%s_%s" , fileName, cn. hutool. core. date. DateUtil. today ( ) , IdUtil . fastSimpleUUID ( ) ) , false , true ) ; return true ; } return false ; } private static String defaultServerName ( ) { return Optional . ofNullable ( SpringUtil . getApplicationContext ( ) ) . map ( ApplicationContext :: getApplicationName ) . orElse ( "NULL" ) ; }
}
实战
初始化操作
implements CommandLineRunner
项目开始则执行以下代码,做个钩子,项目关闭时会触发该线程业务逻辑
@Override public void run ( String . . . args) { Runtime . getRuntime ( ) . addShutdownHook ( new Thread ( shutdownHook) ) ; }
执行 本地缓存数据存入文件 的线程任务
这里的init
方法是项目一启动会执行,将文件数据放进本地缓存中初始化 这里的run
方法是线程执行业务,项目结束运行,钩子触发该业务将本地缓存数据存放进文件中
@Scope ( ConfigurableBeanFactory . SCOPE_SINGLETON )
@Component
public class ShutdownHook implements Runnable { private final static Logger log = LoggerFactory . getLogger ( ShutdownHook . class ) ; private static final List < Persistence > canBeHookList = new ArrayList < > ( ) ; @Value ( "${server-node.id}" ) private String nodeId; @Value ( "${spring.application.name}" ) private String applicationName; @Resource private MonitorThread monitorThread; @PostConstruct public void init ( ) { PersistencePath . serverId = nodeId; PersistencePath . serverName = applicationName; SmsQueueManage . getInstance ( ) . loadLocalData ( ) ; MemoryParamCache . getInstance ( ) . loadLocalData ( ) ; } @Override public void run ( ) { Thread . currentThread ( ) . setName ( "ShutdownHook_Thread" ) ; log. info ( "【sms-rules退出 - Thread:{}】- 钩子回调 开始..." , Thread . currentThread ( ) . getName ( ) ) ; monitorThread. stopMonitorAndAllThread ( ) ; try { Thread . sleep ( 1000 ) ; } catch ( InterruptedException e) { log. error ( Thread . currentThread ( ) . getName ( ) + ": 线程休眠异常" , e) ; } log. info ( "等待持久化队列管理类 size:{}" , canBeHookList. size ( ) ) ; for ( Persistence q : canBeHookList) { q. saveData ( ) ; } log. error ( "【sms-rules退出 - Thread:{}】- 钩子回调 完毕" , Thread . currentThread ( ) . getName ( ) ) ; } public static void add ( Persistence p) { canBeHookList. add ( p) ; } public static void remove ( Persistence p) { canBeHookList. remove ( p) ; }
}
持久化工具类
public class MemoryParamCache implements Persistence { private final static Logger log = LoggerFactory . getLogger ( MemoryParamCache . class ) ; private static final String memoryParamCachePrefixFileName = "memoryParamCache" ; private volatile static MemoryParamCache instance; private MemoryParamCache ( ) { ShutdownHook . add ( this ) ; } public static MemoryParamCache getInstance ( ) { if ( null == instance) { synchronized ( MemoryParamCache . class ) { if ( null == instance) { instance = new MemoryParamCache ( ) ; } } } return instance; } @Override public void saveData ( ) { ObjectOutputStream oos = null ; String path = "" ; try { path = PersistencePath . createFile ( memoryParamCachePrefixFileName) ; log. info ( "【MemoryParamCache - saveData】持久化内存参数到文件 | 开始 | path:{}" , path) ; oos = new ObjectOutputStream ( new FileOutputStream ( path) ) ; oos. writeObject ( RuleSymbol . cityMap) ; log. info ( "【MemoryParamCache - saveData】持久化内存参数到文件 | 结束 | path:{} | cityMap:{}" , path , RuleSymbol . cityMap. size ( ) ) ; } catch ( Exception e) { log. error ( "【MemoryParamCache - 持久化内存参数到文件】异常 | path:{}" , path, e) ; } finally { try { if ( oos != null ) { oos. close ( ) ; } } catch ( IOException ioe) { } } } public void loadLocalData ( ) { ObjectInputStream ois = null ; String path = "" ; try { path = PersistencePath . getPath ( memoryParamCachePrefixFileName) ; log. info ( "【MemoryParamCache - loadLocalData】内存参数缓存文件-->-->-->-->加载到内存开始... | path:{}" , path) ; ois = new ObjectInputStream ( new FileInputStream ( path) ) ; RuleSymbol . cityMap = ( ConcurrentHashMap < String , String > ) ois. readObject ( ) ; log. info ( "【MemoryParamCache - loadLocalData】内存参数缓存文件-->-->-->-->加载到内存 结束 | path:{} | cityMap:{}" , path, RuleSymbol . cityMap. size ( ) ) ; } catch ( Exception e) { log. error ( "【sms-rules启动 - 加载持久化后的内存参数】异常 | path:{}" , path, e) ; } finally { if ( ois != null ) { try { ois. close ( ) ; } catch ( IOException e) { } boolean b = PersistencePath . delFile ( memoryParamCachePrefixFileName) ; log. info ( "【MemoryParamCache - loadLocalData】STEP-TWO 删除缓存数据文件:{}" , b) ; } } } }