个人代码库速查

抽象类实现接口某个方法,再定义抽象方法(模版方法设计模式)

抽象类定义的抽象方法都是让子类实现的,也就是说扩展的抽象方法都在子类定制,共性的方法都可以在抽象类里面实现
例如下面这个例子,我们想在某个接口方法执行的时候 再执行某些自定义方法
就可以再抽象类里面实现这个接口方法,然后再定义几个抽象方法让子类去实现
public interface Job {
  void execute(JobExecutionContext context)
        throws JobExecutionException;
}

public abstract class AbstractJob implements Job {
public abstract void beforeExecuteJob(JobExecutionContext jobExecutionContext) throws JobExecutionException;
public abstract void afterExecuteJob(JobExecutionContext jobExecutionContext) throws JobExecutionException;
public abstract void executeJob(JobExecutionContext jobExecutionContext) throws JobExecutionException;
    @Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
    this.beforeExecuteJob(jobExecutionContext);
    MasterSelector masterSelector = MasterSelector.getInstance();
    if (masterSelector.isMaster()) {
        masterSelector.increaseJobNum();
        try {
            long excuteTimeOut = jobExecutionContext.getJobDetail().getJobDataMap().getLong(Constants.TASK_EXCUETE_TIMEOUT_KEY);
            Future<?> future = ExcuteTaskThreadPool.getThreadPoolExecutor().submit(new Thread(() -> {
                try {
                    executeJob(jobExecutionContext);
                } catch (JobExecutionException e) {
                    log.error("excute job error");
                }
            }));
            future.get(excuteTimeOut, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("excute job timeout", e);
            //TODO 报警监控
        }  finally {
            masterSelector.decreaseJobNum();
        }
    }
    this.afterExecuteJob(jobExecutionContext);
}
}

抽象类+策略模式

父类定义的抽象方法子类都要实现,有时候某些方法不想子类实现,我们就可以使用抽象类+接口方式,
如果子类一旦有点多,都实现这个接口就没发做到代码重用, 这时候就可以使用策略模式
例如下面的flyable 就是变化的部分,我们把变化的部分抽象成接口
abstarct class Duck{
 @Setter
 Flyable flyable;
 public void swim(){
 //
 }

 public abstract void display();

 public void performFly(){
    flyable.fly();
 }
}

public interface Flyable{
 void flay();
}

public class FlyWithWing implements Flyable{
   public void fly(){
   //....
   }
}

public class GreenDuck extends Duck{
   public GreenDuck(){
    this.flyable=new FlyWithWing();
   }

   @Override
   public void display(){

   }
}

double check

private final Map<String, String> myCache = new ConcurrentHashMap<String, String>(256);
   public String getValue(String name) {
       String value = myCache.get(name);
       //check one
       if (value == null) {
           synchronized (this.myCache) {
               value = myCache.get(name);
               //check two
               if (value == null) {
                   value = getValueFromDB();
               }
               myCache.put(value, value);
           }
       }
       return value;
   }

   public String getValueFromDB() {
       return new Random().nextInt(100) + "";
   }

 // booolean 类型double check
 private volatile boolean isInitialized = false;
 if (!isInitialized) {
     synchronized (Object.class) {
       if (!isInitialized) {
       //....
       isInitialized=true;
       }

去锁cas-boolean

private static AtomicBoolean flag = new AtomicBoolean();

public void test(){
    if (flag.compareAndSet(false, true)) {
    ///
    }else{
    ////
    }
}

去锁-future

假如有这样一个业务场景,从数据库里面查询某个key的值,并将查询到的值缓存到本地。
如果并发的去查询某个key的值,怎么保证只会调用一次数据库。

//有锁版本-上面的double check
protected String getWithLock(String key, String defaultValue) {
        ConfigValue configValue = readCache(key);
        if (configValue == null) {
            synchronized (object) {
                configValue = readCache(key);
                if (configValue == null) {
                    configValue = get(key);
                    writeCache(key, configValue);
                }
            }
        }
   return configValue.getValue() == null ? defaultValue : configValue.getValue();
 }

//无锁版本
 private ConcurrentMap<String, ConfigFuture> configFutures = new ConcurrentHashMap<String, ConfigFuture>();
 protected String get(String key, String defaultValue) {
        //读
        ConfigValue configValue = readCache(key);
        if (configValue == null) {
            ConfigFuture existingFuture = null;
            //无锁版本1
            ConfigFuture future = new ConfigFuture(key);
            //putIfAbsent可以巧妙避免同时生成多个future
            existingFuture = configFutures.putIfAbsent(key, future);
            if (existingFuture != null) {
                log.info("wait future");
                // wait for other threads to load the config
                try {
                    configValue = existingFuture.get();
                } catch (Exception e) {
                }
            } else {
                // load the config and notify other threads
                try {
                    configValue = get(key);
                    future.setResult(configValue);
                    writeCache(key, configValue);
                } catch (Exception e) {
                    future.setResult(e);
                } finally {
                    configFutures.remove(key);
                }
            }


            //无锁版本2 多次穿透数据库,多线程可能会生成多个,new ConfigFuture
               /*ConfigFuture future2 = configFutures.get(key);
               if(future2==null){
                   future2 = configFutures.get(key);
                   if(future2==null){
                       log.info("future2 is null");
                       configFutures.put(key, new ConfigFuture(key));
                       configValue = get(key);
                       writeCache(key, configValue);
                   }
                   //dd
               }else{
                   try {
                       configValue = future2.get();
                   } catch (Exception e) {
                  }
              }*/


 }

 //自定义future
 public class ConfigFuture implements Future<ConfigValue> {

     private String key;
     private CountDownLatch latch;
     private Object result;

     public ConfigFuture(String key) {
         this.key = key;
         latch = new CountDownLatch(1);
     }

     @Override
     public boolean cancel(boolean arg0) {
         return false;
     }

     @Override
     public ConfigValue get() throws InterruptedException, ExecutionException {
         latch.await();
         if (result instanceof Throwable) {
             throw new ExecutionException((Throwable) result);
         }
         return (ConfigValue) result;
     }

     @Override
     public ConfigValue get(long arg0, TimeUnit arg1)
             throws InterruptedException, ExecutionException, TimeoutException {
         latch.await(arg0, arg1);
         if (result instanceof Throwable) {
             throw new ExecutionException((Throwable) result);
         }
         return (ConfigValue) result;
     }

     @Override
     public boolean isCancelled() {
         return false;
     }

     @Override
     public boolean isDone() {
         return result != null;
     }

     public void setResult(Object result) {
         this.result = result;
         latch.countDown();
     }

 }

tempate

public class RedisDaoTemplate {
    @Autowired
    private RedisPool redisPool;

    public <T> T execute(RedisCallback<T> rc) throws Exception {
        Jedis jedis = null;
        List<Object> object = null;
        try {
            // 用默认的db 0;
            jedis = redisPool.getJedis();
            return rc.doInRedis(jedis);
        }
        finally {
            redisPool.returnJedis(jedis);
        }
    }
}
public interface RedisCallback<T> {
    T doInRedis(Jedis jedis) throws Exception;
}

一些常用命名方式

xxProvider ( 定义了建立,配置,得到,管理和控制0个或多个对象Manager,一个应用在运行时可能访问0个或者多个)
例如:CachingProvider、ConfigProvider

xxManager(对象管理器)
例如: CachingManager、ConfigManager

xxListener(监听器,当有变动当时候,会通知)
例如:
    ConfigChangeListener
    public interface ConfigChangeListener {
        void onKeyUpdated(String key, String value);
        void onKeyAdded(String key, String value);
        void onKeyRemoved(String key);
    }

    NodeCacheListener:
    public interface NodeCacheListener{
        /**
         * Called when a change has occurred
         */
        public void     nodeChanged() throws Exception;
    }