浅谈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、装饰者模式

输入输出流

时间: 2024-12-28 19:15:40

浅谈JAVA设计模式的相关文章

浅谈-Java设计模式之动态代理

动态代理模式(Dynamic Proxy Pattern): 在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface).另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的. 首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的: InvocationHandler该接口唯一方法 invoke(Object proxy, Method method, Object[] args) Object

浅谈JAVA设计模式之——享元模式(Flyweight)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45568799 一.概述 运用共享技术有效地支持大量细粒度的对象. 二.适用性 当都具备下列情况时,使用Flyweight模式: 1.一个应用程序使用了大量的对象. 2.完全由于使用大量的对象,造成很大的存储开销. 3.对象的大多数状态都可变为外部状态. 4.如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象. 5.应用程序不依赖于对象标识.由于Flyweight对

浅谈JAVA设计模式之——抽象工厂模式(AbstractFactoty)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45440309 一.概述: 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类. 二.为何使用     工厂模式是我们最常用的模式了,著名的Jive论坛 ,就大量使用了工厂模式,工厂模式在Java程序系统可以说是随处可见. 为什么工厂模式是如此常用?因为工厂模式就相当于创建实例对象的new,我们经常要根据类Class生成实例对象,如A a=new A() 工厂模式也

浅谈JAVA设计模式之——解析器模式(Interpreter)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45599443 一.概述 给定一个语言,定义它的文法的一种表示,并定义一个解释器,这个解释器使用该表示来解释语言中的句子. 二.适用性 当有一个语言需要解释执行,并且你可将该语言中的句子表示为一个抽象语法树时,可使 用解释器模式.而当存在以下情况时该模式效果最好: 1.该文法简单对于复杂的文法,文法的类层次变得庞大而无法管理. 2.效率不是一个关键问题最高效的解释器通常不是通过直接

浅谈JAVA设计模式之——组合模式(Composite)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45458081 一.概述 将对象组合成树形结构以表示"部分-整体"的层次结构."Composite使得用户对单个对象和组合对象的使用具有一致性. 二.适用性 1.你想表示对象的部分-整体层次结构. 2.你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象. 三.参与者 1.Component 为组合中的对象声明接口. 在适当的情况下,实现

浅谈JAVA设计模式之——观察者模式(Observer)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45600577 一.概述 定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新. 二.适用性 1.当一个抽象模型有两个方面,其中一个方面依赖于另一方面. 将这二者封装在独立的对象中以使它们可以各自独立地改变和复用. 2.当对一个对象的改变需要同时改变其它对象,而不知道具体有多少对象有待改变. 3.当一个对象必须通知其它对象,而它又不

浅谈JAVA设计模式之——外观模式

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45568655 一.概述 为子系统中的一组接口提供一个一致的界面,Facade模式定义了一个高层接口,这个接口使得这一子系统更加容易使用. 二.适用性 1.当你要为一个复杂子系统提供一个简单接口时.子系统往往因为不断演化而变得越来越 复杂.大多数模式使用时都会产生更多更小的类.这使得子系统更具可重用性,也更容 易对子系统进行定制,但这也给那些不需要定制子系统的用户带来一些使用上的困

浅谈JAVA设计模式之——装饰模式(Decorator)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45464445 一.概述 动态地给一个对象添加一些额外的职责.就增加功能来说,Decorator模式相比生成子类更为灵活. 二.适用性 1.在不影响其他对象的情况下,以动态.透明的方式给单个对象添加职责. 2.处理那些可以撤消的职责. 3.当不能采用生成子类的方法进行扩充时. 三.参与者 1.Component 定义一个对象接口,可以给这些对象动态地添加职责. 2.Concrete

浅谈JAVA设计模式之——命令模式(Command)

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/45569323 一.概述 将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化:对请求排队或记录请求日志,以及支持可撤消的操作. 二.适用性 1.抽象出待执行的动作以参数化某对象. 2.在不同的时刻指定.排列和执行请求. 3.支持取消操作. 4.支持修改日志,这样当系统崩溃时,这些修改可以被重做一遍. 5.用构建在原语操作上的高层操作构造一个系统. 三.参与者 1.Co