浅谈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 }
View Code

     调用线程池对象

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 }
View Code

activemq处理使用生产者消费者模式

 

4、简单工厂模式

5、装饰者模式

    输入输出流

以上是关于浅谈JAVA设计模式的主要内容,如果未能解决你的问题,请参考以下文章

浅谈JAVA设计模式之——单例模式(Singleton)

十年Java”老兵“浅谈源码的七大设计模式

[Android&amp;Java]浅谈设计模式-代码篇:观察者模式Observer

浅谈java领域模式分层实现

浅谈java static

浅谈Java的学习