本文作为一个记录,记录在开发过程中使用到的设计模式,以后做规整。
多种设计模式相结合的案例
并发工具
用到的设计模式
ThreadMDCUtil:装饰器模式(Decorator Pattern)
Beans:策略模式(Strategy Pattern)
InvokerUtil:命令模式(Command Pattern)
直接上代码
import cn.hutool.core.bean.BeanUtil;
import com.rc.framework.common.util.thread.InvokerUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.function.BiConsumer;
import java.util.function.Consumer;
import java.util.function.Function;
public class Beans implements Serializable {
/**
*
* @param toList
* @param fromList
* @param eqFun
* @param <T>
*/
public static<T,R> void addAllToListNotExist(List<T> toList,List<T> fromList,Function<T,R> eqFun){
if (CollectionUtils.isEmpty(fromList)){
return;
}
fromList.forEach(data-> addToListNotExist(toList,data,eqFun));
}
/**
*
* @param list
* @param t
* @param eqFun
* @param <T>
*/
public static<T,R> void addToListNotExist(List<T> list,T t,Function<T,R> eqFun){
if (list.stream().anyMatch(data->{
Object o1 = eqFun.apply(data);
Object o2 = eqFun.apply(t);
if (o1==o2){
return true;
}
if (o1 == null){
return false;
}
return o1.equals(o2);
})){
return;
}
list.add(t);
}
/**
* copy 并创建一个新的对象
*
* @param b
* @param targetClass
* @param <T>
* @return
*/
public static <T> T newObj(Object b, Class<T> targetClass) {
if (b == null) {
return null;
}
T instantiate = BeanUtils.instantiateClass(targetClass);
BeanUtil.copyProperties(b, instantiate);
return instantiate;
}
/**
* forEach并行执行
*
* @param action
* @param <T>
* @return
*/
public static <T> void forEachConcurrent(Collection<T> coll,int invokerNum, Consumer<? super T> action) {
if (action == null || coll==null || coll.isEmpty()) {
return;
}
if (invokerNum > coll.size()) {
invokerNum = coll.size();
}
ConcurrentLinkedQueue<T> queue = new ConcurrentLinkedQueue<>(coll);
InvokerUtil.Invoker[] invokers = new InvokerUtil.Invoker[invokerNum];
for(int i=0;i<invokerNum;i++){
invokers[i] = ()->{
T data;
while(null != (data = queue.poll())) {
action.accept(data);
}
};
}
InvokerUtil.invoiceMulti(invokers);
}
/**
* forEach并行执行
*
* @param action
* @param <T>
* @return
*/
public static <K,T> void forEachConcurrent(Map<? super K, ? super T> map,int invokerNum,BiConsumer<? super K, ? super T> action) {
if (action == null || map==null || map.isEmpty()) {
return;
}
if (invokerNum > map.size()) {
invokerNum = map.size();
}
ConcurrentLinkedQueue<Map.Entry<? super K, ? super T>> queue = new ConcurrentLinkedQueue<>(map.entrySet());
InvokerUtil.Invoker[] invokers = new InvokerUtil.Invoker[invokerNum];
for(int i=0;i<invokerNum;i++){
invokers[i] = ()->{
Map.Entry<? super K, ? super T> data;
while(null != (data = queue.poll())) {
action.accept((K)data.getKey(),(T)data.getValue());
}
};
}
InvokerUtil.invoiceMulti(invokers);
}
/**
* copy 并创建一个新集合
*
* @param b
* @param targetClass
* @param <T>
* @return
*/
public static <T,R> List<R> newObj(List<T> b, final Class<R> targetClass) {
return newObj(b, q-> newObj(q, targetClass));
}
/**
* copy 并创建一个新集合
*
* @param list
* @param converter
* @param <T>
* @return
*/
public static <T,R> List<R> newObj(List<T> list,Function<T,R> converter) {
if (CollectionUtils.isEmpty(list)) {
return null;
}
ArrayList<R> temp = new ArrayList<>();
for (T ob : list) {
temp.add(converter.apply(ob));
}
return temp;
}
/**
* @param b
* @param <T>
* @return
*/
public static <T> T choseOne(List<T> b) {
if (CollectionUtils.isEmpty(b)) {
return null;
}
return b.get(0);
}
/**
* @param b
* @param <T>
* @return
*/
public static <T> T choseOne(T ...b) {
if (b==null || b.length<1) {
return null;
}
return b[0];
}
/**
* 判断字段属性值是否在集合中
*
* @param list
* @param func
* @param propVal
* @param <T>
* @param <R>
* @return
*/
public static <T, R> boolean propIsExistObjList(List<? extends T> list, Function<T, R> func, R propVal) {
if (propVal == null || CollectionUtils.isEmpty(list)) {
return false;
}
return list.stream().anyMatch(d -> propVal.equals(func.apply(d)));
}
/**
* 获取对象中的属性
*
* @param o
* @param func
* @param defaultVal
* @param <T>
* @param <R>
* @return
*/
public static <T, R> R getAttrValue(T o, Function<T, R> func, R defaultVal) {
if (o==null){
return defaultVal;
}
R result = func.apply(o);
return result==null?defaultVal:result;
}
/**
* 获取属性值
*
* @param list
* @param getFun
* @param <T>
* @param <R>
* @return
*/
public static<T,R> List<R> getPropertyList(List<? extends T> list, Function<T, R> getFun) {
if (CollectionUtils.isEmpty(list)){
return null;
}
List<R> result = new ArrayList<>();
list.forEach(d -> result.add(getFun.apply(d)));
return result;
}
/**
* 获取属性值
*
* @param list
* @param eqFun
* @param propVal
* @param getFun
* @param <T>
* @param <R>
* @return
*/
public static<T, Q,R> R getPropInObjListEqProp(List<? extends T> list, Function<T, Q> eqFun, Q propVal, Function<T, R> getFun) {
T t = getObjListEqProp(list, eqFun, propVal);
if (t == null){
return null;
}
return getFun.apply(t);
}
/**
* 获取属性值
*
* @param list
* @param eqFun
* @param propVal
* @param <T>
* @return
*/
public static<T,Q> T getObjListEqProp(List<? extends T> list, Function<T, Q> eqFun, Q propVal) {
if (propVal == null || CollectionUtils.isEmpty(list)) {
return null;
}
T t = list.stream().filter(d -> propVal.equals(eqFun.apply(d))).findFirst().orElse(null);
return t;
}
/**
* copy对象属性 当目标对象属性为空时
*/
public static <T, R> void copyPropIfTargetEmpty(T source, T target, Map<Function<T, R>, BiConsumer<T, R>> funMap) {
if (funMap == null || funMap.size() < 1) {
return;
}
funMap.forEach((get, set) -> {
R targetPropVal = get.apply(target);
if (targetPropVal == null || StringUtils.isBlank(targetPropVal.toString())) {
set.accept(target, get.apply(source));
}
});
}
/**
*
* @param o
* @param r
* @param <T>
* @return
*/
public static<T> T isNull(T o,T r){
if (o==null){
return r;
}
return o;
}
/**
*
* @param o
* @param r
* @param <T>
* @return
*/
public static<T> T isEmpty(T o,T r){
if (o==null){
return r;
}
if(StringUtils.isBlank(o.toString())){
return r;
}
return o;
}
/**
*
* @param o
* @param replaceFun
* @param <T>
* @return
*/
public static<T,R> R isNull(T o,Function<T,R> replaceFun){
if (o==null){
return null;
}
return replaceFun.apply(o);
}
/**
*
* @param o
* @return
* @param <T>
* @param <Q>
*/
public static<T,Q extends Collection<T>> void ifNotEmpty(Q o,Consumer<Q> replaceFun){
if (o==null){
return;
}
if(CollectionUtils.isEmpty(o)){
return;
}
replaceFun.accept(o);
}
/**
*
* @param o
* @return
* @param <T>
* @param <Q>
*/
public static<T,Q extends Collection<T>> void forNotEmpty(Q o,Consumer<T> replaceFun){
if (o==null){
return;
}
if(CollectionUtils.isEmpty(o)){
return;
}
for (T t:o){
replaceFun.accept(t);
}
}
/**
*
* @param o
* @param r
* @return
* @param <T>
* @param <Q>
*/
public static<T,Q extends Collection<T>> Q isEmpty(Q o,Q r){
if (o==null){
return r;
}
if(CollectionUtils.isEmpty(o)){
return r;
}
return o;
}
/**
*
* @param list
* @param objs
* @return
*/
public static boolean collectionContainsAny(List list,Object ...objs){
if (CollectionUtils.isEmpty(list) || objs==null){
return false;
}
List<Object> contains = Arrays.asList(objs);
for (Object o:list){
if (contains.contains(o)){
return true;
}
}
return false;
}
/**
*
* @param a
* @param b
* @return
*/
public static boolean eq(Object a,Object b){
if (a==b){
return true;
}
return a!=null && a.equals(b);
}
/**
*
* @param a
* @param b
* @return
*/
public static boolean eqAny(Object a,Object ...b){
if (b==null){
return false;
}
for (Object i:b){
if (eq(a,i)){
return true;
}
}
return false;
}
/**
*
* @param list
* @param keyFun
* @return
* @param <K>
* @param <V>
*/
public static <K,V> Map<K,V> toMap(Collection<V> list,Function<V,K> keyFun){
if (CollectionUtils.isEmpty(list)){
return new HashMap<>();
}
Map<K,V> result = new LinkedHashMap<>(list.size());
list.forEach(data-> result.put(keyFun.apply(data),data));
return result;
}
}
import com.rc.framework.common.util.log.ThreadMDCUtil;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
@Slf4j
public abstract class InvokerUtil {
//核心线程数,超过则放入等待队列,若等待队列已满(表示没有空闲线程来执行当前提交的任务)则创建新的线程,若线程数超过最大线程限制则抛出Reject异常
//最大线程
//非核心线程最大空闲存活时间为60s
//核心现场池,总要业务
private static final ExecutorService CORE_THREAD_POOL = new ThreadPoolExecutor(
20,
200,
60,
TimeUnit.SECONDS,
new SynchronousQueue<>());
//非核心现场池,相对总要业务
private static final ExecutorService SYNC_THREAD_POOL = new ThreadPoolExecutor(
20,
200,
60,
TimeUnit.SECONDS,
new SynchronousQueue<>());
//次要现场池
private static final ExecutorService SECONDARY_THREAD_POOL = new ThreadPoolExecutor(
20,
200,
60,
TimeUnit.SECONDS,
new SynchronousQueue<>());
/**
* 异步执行优先 线程池满了转同步
*
* @param invokers
* @throws Throwable
*/
public static void invoiceAsyncMulti(Invoker... invokers) {
if (invokers == null || invokers.length < 1) {
return;
}
for (Invoker invoker : invokers) {
if (invoker == null) {
continue;
}
try {
SYNC_THREAD_POOL.submit(ThreadMDCUtil.wrap(new InvokerCallable(invoker), MDC.getCopyOfContextMap()));
} catch (RejectedExecutionException e) {
log.warn("Invoker-异步线程池耗尽 转同步");
invoker.invoke();
}
}
}
/**
* @param invokers
* @throws Throwable
*/
public static void invoiceMulti(List<Invoker> invokers) {
if (invokers == null || invokers.size() < 1) {
return;
}
invoiceMulti(invokers.toArray(new Invoker[]{}));
}
/**
* @param invokers
* @throws Throwable
*/
public static void invoiceMulti(Invoker... invokers) {
if (invokers == null || invokers.length < 1) {
return;
}
//只有单个任务时,就不创建异步线程了
if (invokers.length == 1) {
invokers[0].invoke();
return;
}
List<Future<Object>> futures = new ArrayList<>();
for (Invoker invoker : invokers) {
try {
if (invoker == null) {
continue;
}
futures.add(CORE_THREAD_POOL.submit(ThreadMDCUtil.wrap(new InvokerCallable(invoker), MDC.getCopyOfContextMap())));
} catch (RejectedExecutionException e) {
invoker.invoke();
}
}
for (Future<Object> ft : futures) {
try {
ft.get();
} catch (Exception e) {
log.error("invokeMulti fail", e);
throw new RuntimeException(e);
}
}
}
/**
* @param second
* @param invokers
* @throws Throwable
*/
public static void invoiceMulti(int second, Invoker... invokers) throws TimeoutException {
if (invokers == null || invokers.length < 1) {
return;
}
List<Future<Object>> futures = new ArrayList<>();
for (Invoker invoker : invokers) {
futures.add(SYNC_THREAD_POOL.submit(ThreadMDCUtil.wrap(new InvokerCallable(invoker), MDC.getCopyOfContextMap())));
}
for (Future<Object> future : futures) {
try {
future.get(second, TimeUnit.SECONDS);
} catch (TimeoutException e) {
throw e;
} catch (Exception e) {
log.error("invokeMulti fail", e);
throw new RuntimeException(e);
}
}
}
/**
* @param millis
* @param invokers
* @throws Throwable
*/
public static void invoiceMultiMillis(int millis, Invoker... invokers) throws TimeoutException {
if (invokers == null || invokers.length < 1) {
return;
}
List<Future<Object>> futures = new ArrayList<>();
for (Invoker invoker : invokers) {
futures.add(SYNC_THREAD_POOL.submit(ThreadMDCUtil.wrap(new InvokerCallable(invoker), MDC.getCopyOfContextMap())));
}
for (Future<Object> future : futures) {
try {
future.get(millis, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
throw e;
} catch (Exception e) {
log.error("invokeMulti fail", e);
throw new RuntimeException(e);
}
}
}
/**
* @param second
* @param invokers
* @throws Throwable
*/
public static void invoiceMultiNoMatter(int second, Invoker... invokers) {
try {
invoiceMulti(second, invokers);
} catch (Exception e) {
log.error("invokeMulti fail", e);
}
}
/**
* @param millis
* @param invokers
* @throws Throwable
*/
public static boolean invoiceMultiNoMatterMillis(int millis, Invoker... invokers) {
try {
invoiceMultiMillis(millis, invokers);
return true;
} catch (Exception e) {
log.error("invokeMulti fail", e);
return false;
}
}
/**
* @param invoker
* @throws Throwable
*/
public static void invoiceMultiAsyn(Invoker invoker) {
if (invoker == null) {
return;
}
SYNC_THREAD_POOL.submit(ThreadMDCUtil.wrap(new InvokerCallable(invoker), MDC.getCopyOfContextMap()));
}
/**
* @param invoker
* @throws Throwable
*/
public static void invoiceMultiAsynNoMatter(Invoker invoker) {
if (invoker == null) {
return;
}
try {
SECONDARY_THREAD_POOL.submit(ThreadMDCUtil.wrap(new InvokerCallable(invoker), MDC.getCopyOfContextMap()));
} catch (Exception e) {
log.warn("Invoker-异步线程池耗尽,丢弃", e);
}
}
/**
* @param time
*/
public static void sleep(long time) {
try {
Thread.sleep(time);
} catch (InterruptedException e) {
log.warn("Thread.sleep err", e);
}
}
public interface Invoker {
void invoke();
}
private static class InvokerCallable implements Callable<Object> {
protected Invoker invoker;
InvokerCallable(Invoker invoker) {
this.invoker = invoker;
}
@Override
public Object call() throws Exception {
invoker.invoke();
return true;
}
}
}
import org.slf4j.MDC;
import java.util.Map;
import java.util.concurrent.Callable;
public class ThreadMDCUtil {
public static void setTraceIdIfAbsent() {
if (MDC.get(LogMDCUtil.LOG_ID) == null) {
MDC.put(LogMDCUtil.LOG_ID, LogMDCUtil.getLogId());
}
}
public static <T> Callable<T> wrap(final Callable<T> callable, final Map<String, String> context) {
return () -> {
if (context == null) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
setTraceIdIfAbsent();
try {
return callable.call();
} finally {
MDC.clear();
}
};
}
public static Runnable wrap(final Runnable runnable, final Map<String, String> context) {
return () -> {
if (context == null) {
MDC.clear();
} else {
MDC.setContextMap(context);
}
setTraceIdIfAbsent();
try {
runnable.run();
} finally {
MDC.clear();
}
};
}
}
评论区