引用对象的使用和易产生bug的示例

来源:互联网 发布:淘宝买家秀福利怎么找 编辑:程序博客网 时间:2024/05/20 11:46

QuoteTest(引用对象技巧)  

复制代码
  1 import java.util.ArrayList;  2 import java.util.HashMap;  3 import java.util.List;  4 import java.util.Map;  5   6 /**  7  * Created by robin on 2016/4/13.  8  * 引用型对向操作总结:  9  * 1.被引用的对象,值改变时,会直接改变引用源的值; 10  * 2.当引用的对象,改变其引用源时,对其操作,只会改变新的引用源的值,并不会影响之前的引用源的值 11  * 3.从map中获取的引用不存在时,需要将新的引用put到map中,map中该位置的值,才会被引入 12  * @author robin 13  */ 14 public class QuoteTest { 15  16     public static void main(String args[]){ 17         Map<String,List<String>> map = new HashMap<String, List<String>>(); 18         for (int i =0;i< 5;i++){ 19             List<String> datalist = new ArrayList<String>(); 20             for (int j=0;j<10;j++){ 21                 datalist.add(i*10+""+j); 22             } 23             map.put(""+i,datalist); 24         } 25         for (List<String> list:map.values()){ 26             System.out.println(listToString(list)); 27         } 28         System.out.println("----------分隔线1-----------"); 29         List<String> tempList =  map.get("3"); 30         tempList.add("avc"); 31         tempList.remove("300"); 32         for (List<String> list:map.values()){ 33             System.out.println(listToString(list)); 34         } 35         System.out.println("----------分隔线2-----------"); 36         List<String> tempList2 =  map.get("2");//tempList 获得map中 key为2的引用 37         List<String> replaceList = new ArrayList<String>(); 38         tempList2 = replaceList;////tempList 获得其他list的引用,失去map中 key为2的引用,此时对templist2做任何操作,影响的时replaceList引用的区域 39         tempList2.add("replaceList的值被改变"); 40         for (List<String> list:map.values()){ 41             System.out.println(listToString(list)); 42         } 43         System.out.println("replaceList的值:"+listToString(replaceList)); 44         System.out.println("----------分隔线3-----------"); 45         List<String> tempList3 =  map.get("2"); 46         tempList3 = replaceList; 47         map.put("2",tempList3); 48         for (List<String> list:map.values()){ 49             System.out.println(listToString(list)); 50         } 51         System.out.println("----------分隔线4-----------"); 52         List<String> notExistList = map.get("5"); 53         if(notExistList == null){ 54             notExistList = new ArrayList<String>(); 55         } 56         notExistList.add("第5行数据添加进来..."); 57         for (List<String> list:map.values()){ 58             System.out.println(listToString(list)); 59         } 60         System.out.println("----------分隔线5-----------"); 61         List<String> notExistList2 = map.get("6"); 62         if(notExistList2 == null){ 63             notExistList2 = new ArrayList<String>(); 64         } 65         notExistList2.add("第6行数据添加进来..."); 66         map.put("6",notExistList2); 67         for (List<String> list:map.values()){ 68             System.out.println(listToString(list)); 69         } 70         System.out.println("----------分隔线5-----------"); 71  72         Map<String,Map<String,String>> mapOne = new HashMap<String, Map<String, String>>(); 73         String keyss = "mapTest"; 74         Map<String,String> mapTwo = new HashMap<String, String>(); 75         mapOne.put(keyss,mapTwo); 76         System.out.println("mapOne的数据:" + mapToString(mapOne)); 77         System.out.println("----------分隔线6-----------"); 78         mapTwo.put("aaa", "aaav"); 79         mapTwo.put("bbb", "bbbv"); 80         mapTwo.put("ccc","cccv"); 81         System.out.println("mapOne的数据:"+mapToString(mapOne)); 82         System.out.println("----------分隔线7-----------"); 83     } 84  85     private static String listToString(List<String> list){ 86         StringBuilder sb = new StringBuilder(""); 87         for (String s:list){ 88             sb.append("["+s+"] "); 89         } 90         return sb.toString(); 91     } 92  93     private static String mapToString(Map<?,?> map){ 94         StringBuilder sb = new StringBuilder(""); 95         for(Map.Entry entry:map.entrySet()){ 96             sb.append("[key:"+entry.getKey()+";value:"+entry.getValue()+"]"); 97         } 98         return sb.toString(); 99     }100 101 }
复制代码

---------------------

引用对象易产生的bug:

2016.05.11

关于引用对象,使用不恰当,很容易给自己挖坑,产生非常严重的bug,进而导致整个系统实际业务的崩溃,而且这种bug很难被查出来。(如果日志记录不够详细,分析不够彻底,要找出这种bug,只能靠上帝保佑)

下面先上bug 代码 demo

 

复制代码
 1 import java.util.Iterator; 2 import java.util.List; 3 import java.util.Vector; 4  5 /** 6  * Created by robin on 2016/5/11. 7  * 8  * @author robin 9  */10 public class QuoteBugDemo {11 12     private static List<Integer> publicNums = new Vector<Integer>();13 14     public static void main(String args[]) throws InterruptedException {15         initPublicNums();//初始化公共数据源16 17         timeTask(1);//模拟执行定时任务118 19         timeTask(2);//模拟执行定时任务220 21     }22 23 24     private static void initPublicNums(){25         for (int i =0;i < 10;i++){26             publicNums.add(i);27         }28     }29 30     /**31      * 这块代码模拟的逻辑:32      * 1.每天获取配置好10个的数据源;33      * 2.检查这10个数据源,当数据源的数据准备好后,开始执行数据同步;34      * 3.从当天的带同步数据源list删除已经同步的数据;35      * @param mark36      * @throws InterruptedException37      */38     private static void timeTask(int mark) throws InterruptedException {39         final long start = System.currentTimeMillis();//程序开始运行时间40         //每天待同步数据源41         List<Integer> dataSources = publicNums;42         StringBuffer sb = new StringBuffer("mark("+mark+");公共数据源数目:"+dataSources.size()+";数据源列表[");43         for (Integer i:dataSources){44             sb.append(i+",");45         }46         sb.append("]");47         System.out.println("日志【"+sb.toString()+"】");48         while(true){49             long seconds = (System.currentTimeMillis() - start) / 1000;50             if(seconds > 15l){51                 System.out.println("运行超过限定时间:15秒,退出");52                 break;53             }54             Iterator<Integer> ite = dataSources.iterator();55             while (ite.hasNext()){//56                 int dataSource = ite.next();57                 boolean flag = isOk(dataSource);58                 if(flag){//数据源数据已准备好59                     System.out.println("对数据源:"+dataSource+"进行数据处理。");//同步数据60                     ite.remove();//待同步数据源删除该数据源61                 }62             }63             if(dataSources.size() != 0){64                 Thread.sleep(1000);65             }else{66                 break;67             }68         }69         System.out.println("定时任务mark["+mark+"]已经执行完毕");70     }71 72     /**73      * 模拟检查数据源是否OK74      * @param dataSource75      * @return76      */77     private static boolean isOk(int dataSource){78         if(dataSource%2 == 0){79             return true;80         }81         return false;82     }83 84 85 }
复制代码

执行结果:

复制代码
 1 日志【mark(1);公共数据源数目:10;数据源列表[0,1,2,3,4,5,6,7,8,9,]】 2 对数据源:0进行数据处理。 3 对数据源:2进行数据处理。 4 对数据源:4进行数据处理。 5 对数据源:6进行数据处理。 6 对数据源:8进行数据处理。 7 运行超过限定时间:15秒,退出 8 定时任务mark[1]已经执行完毕 9 日志【mark(2);公共数据源数目:5;数据源列表[1,3,5,7,9,]】10 运行超过限定时间:15秒,退出11 定时任务mark[2]已经执行完毕
复制代码

定时任务2,执行的时候,数据源只剩1,3,5,7,9。

改进方案:将公共数据源保护起来,仅提供公共数据源的副本:shallow copy和deep copy

核心代码:

复制代码
1 /**2      * 改进方案1:获取公共数据源对象的副本3      * shallow copy:list中 元素引用 仍然是相同的4      * @return5      */6     private static List<Integer> getPublicNums(){7         List<Integer> clone = new ArrayList<Integer>(publicNums);8         return clone;9     }
复制代码

改进后全部代码:

复制代码
 1 import java.util.ArrayList; 2 import java.util.Iterator; 3 import java.util.List; 4 import java.util.Vector; 5  6 /** 7  * Created by robin on 2016/5/11. 8  * 9  * @author robin10  */11 public class QuoteBugDemo {12 13     private static List<Integer> publicNums = new Vector<Integer>();14 15     public static void main(String args[]) throws InterruptedException {16         initPublicNums();//初始化公共数据源17 18         timeTask(1);//模拟执行定时任务119 20         timeTask(2);//模拟执行定时任务221 22     }23 24 25     private static void initPublicNums(){26         for (int i =0;i < 10;i++){27             publicNums.add(i);28         }29     }30 31     /**32      * 改进方案1:获取公共数据源对象的副本33      * shallow copy:list中 元素引用 仍然是相同的34      * @return35      */36     private static List<Integer> getPublicNums(){37         List<Integer> clone = new ArrayList<Integer>(publicNums);38         return clone;39     }40 41     /**42      * 这块代码模拟的逻辑:43      * 1.每天获取配置好10个的数据源;44      * 2.检查这10个数据源,当数据源的数据准备好后,开始执行数据同步;45      * 3.从当天的带同步数据源list删除已经同步的数据;46      * @param mark47      * @throws InterruptedException48      */49     private static void timeTask(int mark) throws InterruptedException {50         final long start = System.currentTimeMillis();//程序开始运行时间51         //每天待同步数据源52         List<Integer> dataSources = getPublicNums();//改进方案153         StringBuffer sb = new StringBuffer("mark("+mark+");公共数据源数目:"+dataSources.size()+";数据源列表[");54         for (Integer i:dataSources){55             sb.append(i+",");56         }57         sb.append("]");58         System.out.println("日志【"+sb.toString()+"】");59         while(true){60             long seconds = (System.currentTimeMillis() - start) / 1000;61             if(seconds > 15l){62                 System.out.println("运行超过限定时间:15秒,退出");63                 break;64             }65             Iterator<Integer> ite = dataSources.iterator();66             while (ite.hasNext()){//67                 int dataSource = ite.next();68                 boolean flag = isOk(dataSource);69                 if(flag){//数据源数据已准备好70                     System.out.println("对数据源:"+dataSource+"进行数据处理。");//同步数据71                     ite.remove();//待同步数据源删除该数据源72                 }73             }74             if(dataSources.size() != 0){75                 Thread.sleep(1000);76             }else{77                 break;78             }79         }80         System.out.println("定时任务mark["+mark+"]已经执行完毕");81     }82 83     /**84      * 模拟检查数据源是否OK85      * @param dataSource86      * @return87      */88     private static boolean isOk(int dataSource){89         if(dataSource%2 == 0){90             return true;91         }92         return false;93     }94 95 96 }
复制代码

执行结果:

复制代码
 1 日志【mark(1);公共数据源数目:10;数据源列表[0,1,2,3,4,5,6,7,8,9,]】 2 对数据源:0进行数据处理。 3 对数据源:2进行数据处理。 4 对数据源:4进行数据处理。 5 对数据源:6进行数据处理。 6 对数据源:8进行数据处理。 7 运行超过限定时间:15秒,退出 8 定时任务mark[1]已经执行完毕 9 日志【mark(2);公共数据源数目:10;数据源列表[0,1,2,3,4,5,6,7,8,9,]】10 对数据源:0进行数据处理。11 对数据源:2进行数据处理。12 对数据源:4进行数据处理。13 对数据源:6进行数据处理。14 对数据源:8进行数据处理。15 运行超过限定时间:15秒,退出16 定时任务mark[2]已经执行完毕
0 0
原创粉丝点击