浅谈JAVA设计模式
Posted YOU CAN
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈JAVA设计模式相关的知识,希望对你有一定的参考价值。
没有万行的代码量,就不要想搞清楚设计模式。目前本人代码量大约在六千五百行,2016年需要继续努力,尽快完成万行之约。
工作之余需要,下面提前简单讨论一下设计模式。
1、代理模式
db数据库组件代理ibatis开源组件
1 public static PersistService createPersistClient(String alias) 2 { 3 PersistService service = null; 4 try 5 { 6 service = new PersistServiceProxy(alias); 7 } 8 catch (Exception e) 9 { 10 logger.error("Failed new Instance PersistProxy.", e); 11 } 12 return service; 13 }
PersistService代理PersistServiceProxy(IbatisPersistServiceImpl),减少操作Connection,ResultSet繁琐对象。
2、单例模式
a、实例化线程池使用单例模式
私有化构造方法,对外暴露一个方法创建单例实例,在多线程情况下只允许一个线程处理业务
1 public class BackThreadCaller 2 { 3 4 private static volatile BackThreadCaller instance; 5 private ThreadPoolExecutor pool; 6 private static Logger log = LoggerFactory.getLogger(BackThreadCaller.class); 7 8 private BackThreadCaller() 9 { 10 int corePoolSize = CalendarConsts.getThreadCorePoolSize(); 11 int maximumPoolSize = CalendarConsts.getThreadMaximumPoolSize(); 12 int keepAliveTime = CalendarConsts.getThreadKeepAliveTime(); 13 int QueueSize = CalendarConsts.getThreadQueueSize(); 14 pool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, TimeUnit.SECONDS, 15 new ArrayBlockingQueue<Runnable>(QueueSize), 16 new ThreadPoolExecutor.DiscardPolicy()); 17 } 18 19 public static BackThreadCaller getInstance() 20 { 21 if (instance == null) 22 { 23 synchronized (BackThreadCaller.class) 24 { 25 if (instance == null) 26 { 27 instance = new BackThreadCaller(); 28 } 29 } 30 } 31 log.info("BackThreadCaller:ActiveCount={}|CompletedTaskCount={}|CorePoolSize={}|LargestPoolSize={}|PoolSize={}|TaskCount={}", 32 instance.getActiveCount(),instance.getCompletedTaskCount(), 33 instance.getCorePoolSize(),instance.getLargestPoolSize(),instance.getPoolSize(), 34 instance.getTaskCount()); 35 return instance; 36 } 37 38 public void startAThread(Thread thread) 39 { 40 try 41 { 42 pool.execute(thread); 43 } 44 catch (Exception e) 45 { 46 log.error("Exception", e); 47 } 48 } 49 50 /** 51 * 开始执行一个线程 52 * @param thread 53 */ 54 public void startAThread(Runnable thread) 55 { 56 try 57 { 58 pool.execute(thread); 59 } 60 catch (Exception e) 61 { 62 log.error("Exception", e); 63 } 64 } 65 66 // 正在执行的线程任务数,本例中如果为2,则可以观察两个office是否可以同时工作 67 public int getActiveCount() 68 { 69 return pool.getActiveCount(); 70 } 71 72 // 返回池中的当前线程数 73 public int getPoolSize() 74 { 75 return pool.getPoolSize(); 76 } 77 78 // 返回核心线程数 79 public int getCorePoolSize() 80 { 81 return pool.getCorePoolSize(); 82 } 83 84 // 返回曾经同时位于池中的最大线程数 85 public int getLargestPoolSize() 86 { 87 return pool.getLargestPoolSize(); 88 } 89 90 // 已经完成的任务总数 91 public long getCompletedTaskCount() 92 { 93 return pool.getCompletedTaskCount(); 94 } 95 96 // 曾经计划的任务总数 97 public long getTaskCount() 98 { 99 return pool.getTaskCount(); 100 } 101 102 }
调用线程池对象
1 public void setTaskMessages(final CalendarBean calendarBean) 2 { 3 BackThreadCaller.getInstance().startAThread(new Runnable(){ 4 public void run(){ 5 //业务处理 6 } 7 }); 8 }
b、写日志
使用单例生成唯一一个日志处理类
3、生产者消费者
日志处理类依据生产者消费者模式来处理,多个生产者将数据放入队列,生产者将数据 放入队列就立即返回,logHandler当做消费者一直从队列中消费数据,再将数据生成一个个任务提交到线程池中去处理.
1 /** 2 * 3 * 功能描述:日志上报工具类 4 * 5 */ 6 public class UActionTools 7 { 8 9 private static Logger log = LoggerFactory.getLogger(UActionTools.class); 10 private static volatile UActionTools instance; 11 12 private final ConcurrentLinkedQueue<UserLog> uLogs = new ConcurrentLinkedQueue<UserLog>(); 13 private ThreadPoolExecutor pool; 14 private int delayTime = 60000; 15 private int batchsize = 30; 16 17 /** 18 * 本方法拟采用批量提交的模式来实现. 19 * 还有一种实现方法是:取消arraylist定义,每次把记录保存到pstmt,到一定数量后再executebatch. 20 * 后一种方法需要数据库连接随时保持,占用一个连接,不太好。 21 */ 22 23 private UActionTools() 24 { 25 batchsize = Integer.valueOf(BComponetConfig.getInstance().getProperty( 26 "Logsbatch", "30")); 27 delayTime = Integer.valueOf(BComponetConfig.getInstance().getProperty( 28 "LogsInterval", "60000")); 29 30 pool = new ThreadPoolExecutor(8, 20, 30, TimeUnit.SECONDS, 31 new ArrayBlockingQueue<Runnable>(512), 32 new ThreadPoolExecutor.CallerRunsPolicy()); 33 34 // 实例化线程对象后就立即实例化一个日志处理器并提交到线程池中 35 // 等待线程池调度,之后这个任务将一直运行直到线程池关闭 36 pool.execute(new LogHandler()); 37 38 log.info("start actionlog thread"); 39 } 40 41 public static UActionTools getInstance() 42 { 43 if (instance == null) 44 { 45 synchronized (UActionTools.class) 46 { 47 if (instance == null) 48 { 49 instance = new UActionTools(); 50 } 51 } 52 } 53 return instance; 54 } 55 56 /** 57 * 调用存储线程保存日志信息 58 * 59 * @param ulog 60 */ 61 public void saveAction(UserLog ulog) 62 { 63 64 uLogs.add(ulog); 65 66 } 67 68 /** 69 * 获得当前内存日志信息 70 * 71 * @return ConcurrentLinkedQueue<UserLog> 72 */ 73 public ConcurrentLinkedQueue<UserLog> getForceLists() 74 { 75 return uLogs; 76 } 77 78 // 正在执行的线程任务数,本例中如果为2,则可以观察两个office是否可以同时工作 79 public int getActiveCount() 80 { 81 return pool.getActiveCount(); 82 } 83 84 // 返回池中的当前线程数 85 public int getPoolSize() 86 { 87 return pool.getPoolSize(); 88 } 89 90 // 返回核心线程数 91 public int getCorePoolSize() 92 { 93 return pool.getCorePoolSize(); 94 } 95 96 // 返回曾经同时位于池中的最大线程数 97 public int getLargestPoolSize() 98 { 99 return pool.getLargestPoolSize(); 100 } 101 102 // 已经完成的任务总数 103 public long getCompletedTaskCount() 104 { 105 return pool.getCompletedTaskCount(); 106 } 107 108 // 曾经计划的任务总数 109 public long getTaskCount() 110 { 111 return pool.getTaskCount(); 112 } 113 114 /** 115 * 日志处理类 116 * 117 * 依据生产者消费者模式来处理,多个生产者将数据放入队列,生产者将数据 放入队列就立即返回, 118 * logHandler当做消费者一直从队列中消费数据,再将数据生成一个个任务提交到线程池中去处理. 119 * 120 * 121 * 优点: 1.线程安全,不会丢失数据。 2.生成者放入数据到队列中就立即返回,生产者(主线程)的执行时间更短,之前的实现方式中 122 * 生产者(主线程)还需负责从队列中消费数据,然后才生产一个个任务提交到线程池中处理, 相比 之下缩短了主线程的处理时间,这样也更合理. 123 * 124 * @author zhouguiping 125 * 126 */ 127 private class LogHandler implements Runnable 128 { 129 130 // 队列中没有数据时睡眠时间 131 private final int WAITTIME = 1000; 132 133 @Override 134 public void run() 135 { 136 int count = 0;// 计数器 137 Date writeTime = new Date(); 138 boolean time = false; 139 ConcurrentLinkedQueue<UserLog> uLogQueue = new ConcurrentLinkedQueue<UserLog>(); 140 while (true) 141 { 142 try 143 { 144 UserLog log = uLogs.poll(); 145 if (log == null) 146 { 147 try 148 { 149 // 睡眠1秒钟,防止队列中没有数据时线程在这里空跑 150 Thread.sleep(WAITTIME); 151 } 152 catch (Exception e) 153 {} 154 155 // 如果时间到达了指定的阈值,将已经获取到的值提交 156 time = (System.currentTimeMillis() - writeTime 157 .getTime()) > delayTime; 158 if (time && (uLogQueue.size() > 0)) 159 { 160 pool.execute(new UActionThread(uLogQueue)); 161 uLogQueue = new ConcurrentLinkedQueue<UserLog>(); 162 count = 0; 163 writeTime = new Date(); 164 } 165 continue; 166 } 167 168 uLogQueue.add(log); 169 count++; 170 // 一次性处理的数据大小 171 if (count >= batchsize) 172 { 173 pool.execute(new UActionThread(uLogQueue)); 174 uLogQueue = new ConcurrentLinkedQueue<UserLog>(); 175 count = 0; 176 writeTime = new Date(); 177 } 178 } 179 catch (Throwable e) 180 { 181 // 捕获所有异常,这个线程不能停止除非jvm停止了 182 log.error("UActionTools Log loop thread is exception.", e); 183 } 184 } 185 } 186 } 187 }
activemq处理使用生产者消费者模式
4、简单工厂模式
5、装饰者模式
输入输出流
以上是关于浅谈JAVA设计模式的主要内容,如果未能解决你的问题,请参考以下文章