package com.yy.fastcustom.actualupdate; import java.util.concurrent.BlockingQueue; /** * Created by zzq on 2019/5/16. */ public abstract class ActualDataModelOperationHandler<Data> { private String readWriteFlag; public final String getReadWriteFlag() { return readWriteFlag; } public final void setReadWriteFlag(String readWriteFlag) { this.readWriteFlag = readWriteFlag; } private long readWaitMillis; public final long getReadWaitMillis() { return readWaitMillis; } public final void setReadWaitMillis(long readWaitMillis) { this.readWaitMillis = readWaitMillis; } /** * Update the cache information * * @Return successful return to true * / public abstract boolean removeCache (); /** * Updated data * * @Return successful return to true * / public abstract boolean updateOriginalDataAndCache (); /** * Comprehensive read data (existing cache read, can not read reading database) * * @return */ public abstract Data getOriginalData(); public abstract Date getCacheData (); public abstract void setCacheData (Date date); public final void updateData() throws Exception { BlockingQueue<ActualDataModelOperationHandler> actualDataModels = ActualDataServiceManager.getUpdateQueue(this.getReadWriteFlag()); actualDataModels.put(this); } public final Data readData() { In Flag String = the this .getReadWriteFlag (); IF (ActualDataServiceManager.contains (In Flag)) { Long the startTime = System.currentTimeMillis (); // current number of milliseconds for (; to true ;) { IF (ActualDataServiceManager.noContains (In Flag) || (System.currentTimeMillis () - the startTime> the this .getReadWaitMillis ())) // If the spin time is greater than the set threshold BREAK ; Data retData = this.getCacheData(); if (retData != null) return retData; } } Data retData = this.getCacheData(); if (retData != null) return retData; retData = this.getOriginalData(); if (retData != null) this.setCacheData(retData); return retData; } }
package com.yy.fastcustom.actualupdate; import java.util. * ; import java.util.concurrent. * ; /** * Created by zzq on 2019/5/16. */ public class ActualDataServiceManager { private static volatile List<DataUpdateQueueWrapper> queueList = null; private static Map<String, Object> updateOperationTag = null; private static ExecutorService executor = null; public static void initQueueNum(int size) { if (queueList == null) synchronized (ActualDataServiceManager.class) { if (queueList == null) initBasicObject(size); } } private static void initBasicObject(int size) { int sizeExtend = size * 1000;//hash范围放大1000倍 queueList = new ArrayList<>(sizeExtend); updateOperationTag = new ConcurrentHashMap<>(); executor = new ThreadPoolExecutor( size, size, 60L, TimeUnit.SECONDS, new SynchronousQueue(), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); DataUpdateQueueWrapper ary[] = new DataUpdateQueueWrapper[size]; for (int i = 0; i < size; i++) { DataUpdateQueueWrapper dataUpdateQueueWrapper = new DataUpdateQueueWrapper(); ary[i] = dataUpdateQueueWrapper; executor.submit(dataUpdateQueueWrapper); } for ( int I = 0; I <sizeExtend; I ++) { // generate a virtual node hash queueList.add (ary [I% size]); } } /** The mark * Get Queue * * @param flag * @Return * / public static BlockingQueue <ActualDataModelOperationHandler> getUpdateQueue (String In Flag) throws Exception { IF (queueList == null ) { the throw new new Exception ( "before calling this method, the number of calls initQueueNum update the queue initialization" ); } int hash; int index = flag == null ? 0 : (hash = flag.hashCode()) ^ (hash >>> 16); return queueList.get((queueList.size() - 1) & index).getQueue(); } public static void addFlag(String flag) { updateOperationTag.put(flag, "flagValue"); } public static void removeFlag(String flag) { updateOperationTag.remove(flag); } public static boolean contains(String flag) { return updateOperationTag.containsKey(flag); } public static boolean noContains(String flag) { return !contains(flag); } }
package com.yy.fastcustom.actualupdate; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.LinkedBlockingQueue; /** * Created by zzq on 2019/5/16. */ public class DataUpdateQueueWrapper implements Callable { private volatile BlockingQueue<ActualDataModelOperationHandler> updateQueue = null; { updateQueue = new LinkedBlockingQueue<>(); } public BlockingQueue<ActualDataModelOperationHandler> getQueue() { return updateQueue; } @Override public Object call() throws Exception { for (; true; ) { ActualDataModelOperationHandler actualDataModel = updateQueue.take(); String flag = actualDataModel.getReadWriteFlag(); ActualDataServiceManager.addFlag (In Flag); // here by a separate worker thread loop queue the try { Boolean B1 = actualDataModel.removeCache (); IF (B1) // If the cache deletion fails, and no update is flushed to the database cache; buffer deleted successfully even if updateDbAndCache failed also to ensure the consistency of old data actualDataModel.updateOriginalDataAndCache (); } finally { ActualDataServiceManager.removeFlag(flag); } } } }
package com.yy.fastcustom.actualupdate; /** * Created by zzq on 2019/5/27/027. */ public class TestDataModel extends ActualDataModelOperationHandler<String> { public static void main(String[] args) { // ceshi_hash(); String key = "1"; ActualDataServiceManager.initQueueNum(3); final TestDataModel actualDataModel = new TestDataModel(); actualDataModel.setReadWriteFlag(key); actualDataModel.setReadWaitMillis ( 20 * 1000 ); try { actualDataModel.updateData(); } catch (Exception e) { e.printStackTrace (); } new Thread(() -> { String ret = null ; ret = actualDataModel.readData(); System.out.println("=====end out====" + ret); }).start(); } private static void ceshi_hash() { int p1 = 356349; int p2 = 453546; int p3 = 678345; int p4 = 768678; int p5 = 967897; int r1 = p1 & 2; int r2 = p2 & 2; int r3 = p3 & 2; int r4 = p4 & 2; int r5 = p5 & 2; int r1_ = p1 & 2999; int r2_ = p2 & 2999; int r3_ = p3 & 2999; int r4_ = p4 & 2999; int r5_ = p5 & 2999; System.out.println("===="); } volatile String uu = null; @Override public boolean removeCache() { for (int i = 0; i < 5; i++) { System.out.println("====removeCache==缓存=="); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace (); } } return true; } @Override public boolean updateOriginalDataAndCache() { for (int i = 0; i < 5; i++) { System.out.println ( "Database == ==== updateOriginalDataAndCache ==" ); the try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace (); } if (i == 1) { Uu = "acquires the cache data" ; } } return false; } @Override public void setCacheData(String s) { u = s; System.out.println ( "==== read the database is successful, put it in the cache ==" ); } @Override public String getOriginalData () { return "not found the cache, loaded from the database!" ; } @Override public String getCacheData() { System.out.println ( "==== read cache but did not read ==" ); return null ; } }