您好,登錄后才能下訂單哦!
前幾天工作中,遇到一個并發環境下有人寫了SimpleDateFormat的場景,印象中這個是不能支持多線程的,應該使用ThreadLocal作為每個線程局部變量使用,今天有空,試了下SimpleDateFormat多線程使用,多個線程并發打印對象,代碼如下:
/** ?*?TestDateFormat.java ?*?zhm.test.dateFormat ?*?2018年5月2日下午9:02:07 ?* ?*/ package?zhm.test.dateFormat; import?java.sql.Timestamp; import?java.text.ParseException; import?java.text.SimpleDateFormat; import?java.util.Calendar; import?java.util.Date; import?java.util.Random; /** ?*?@author?zhuheming?TestDateFormat?2018年5月2日下午9:02:07 ?*/ public?class?TestDateFormat?{ ????public?static?TestDateFormat?tdf?=?null; ????SimpleDateFormat?sdf?=?new?SimpleDateFormat("yyyy-MM-dd"); ????public?static?void?main(String[]?args)?{ ????????tdf?=?new?TestDateFormat(); ????????for?(int?i?=?1;?i?<=?9;?i++)?{ ????????????Thread?th?=?new?Thread(new?Runnable()?{ ????????????????@Override ????????????????public?void?run()?{ ????????????????????while?(true)?{ ????????????????????????Random?r?=?new?Random(); ????????????????????????int?k?=?r.nextInt(100); ????????????????????????int?randomSwitch?=?k?%?3; ????????????????????????Calendar?c?=?Calendar.getInstance(); ????????????????????????c.add(Calendar.DATE,?k); ????????????????????????try?{ ????????????????????????????Thread.sleep(100); ????????????????????????????switch?(randomSwitch)?{ ????????????????????????????case?0: ????????????????????????????????String?s1?=?c.get(Calendar.YEAR)?+?"-" ????????????????????????????????????????+?TestDateFormat.formatNumber((c.get(Calendar.MONTH)?+?1))?+?"-" ????????????????????????????????????????+?TestDateFormat.formatNumber((c.get(Calendar.DAY_OF_MONTH))); ????????????????????????????????Date?date1?=?tdf.printDateFormat(s1); ????????????????????????????????String?d1?=?new?Timestamp(date1.getTime()).toString(); ????????????????????????????????d1?=?d1.substring(0,d1.indexOf("?")); ????????????????????????????????if(!s1.equals(d1)){ ????????????????????????????????????System.out.println(s1+"?????"+d1); ????????????????????????????????} ????????????????????????????????break; ????????????????????????????case?1: ????????????????????????????????String?s2?=?c.get(Calendar.YEAR)?+?"-" ????????????????????????????????????????+?TestDateFormat.formatNumber((c.get(Calendar.MONTH)?+?1))?+?"-" ????????????????????????????????????????+?TestDateFormat.formatNumber((c.get(Calendar.DAY_OF_MONTH))); ????????????????????????????????Date?date2?=?TestDateFormat.printStaticDateFormat(s2); ????????????????????????????????String?d2?=?new?Timestamp(date2.getTime()).toString(); ????????????????????????????????d2?=?d2.substring(0,d2.indexOf("?")); ????????????????????????????????if(!s2.equals(d2)){ ????????????????????????????????????System.out.println(s2+"?????"+d2); ????????????????????????????????} ????????????????????????????????break; ????????????????????????????case?2: ????????????????????????????????String?s?=?c.get(Calendar.YEAR)?+?"-" ????????????????????????????????????????+?TestDateFormat.formatNumber((c.get(Calendar.MONTH)?+?1))?+?"-" ????????????????????????????????????????+?TestDateFormat.formatNumber((c.get(Calendar.DAY_OF_MONTH))); ????????????????????????????????Date?date3?=?tdf.printReferenceDateFormat(s); ????????????????????????????????String?d3?=?new?Timestamp(date3.getTime()).toString(); ????????????????????????????????d3?=?d3.substring(0,d3.indexOf("?")); ????????????????????????????????if(!s.equals(d3)){ ????????????????????????????????????System.out.println(s+"?????"+d3); ????????????????????????????????} ????????????????????????????????break; ????????????????????????????default: ????????????????????????????????return; ????????????????????????????} ????????????????????????}?catch?(Exception?e)?{ ????????????????????????} ????????????????????} ????????????????} ????????????}); ????????????th.start(); ????????????try?{ ????????????????th.join(); ????????????}?catch?(InterruptedException?e)?{ ????????????????//?TODO?Auto-generated?catch?block ????????????????e.printStackTrace(); ????????????} ????????} ????} ????public?Date?printReferenceDateFormat(String?str)?{ ????????System.out.println("get?the?ReferenceDateFormat:"?+?sdf); ????????try?{ ????????????return?sdf.parse(str); ????????}?catch?(ParseException?e)?{ ????????????//?TODO?Auto-generated?catch?block ????????????e.printStackTrace(); ????????????return?null; ????????} ????} ????public?static?Date?printStaticDateFormat(String?str)?{ ????????SimpleDateFormat?df1?=?new?SimpleDateFormat("yyyy-MM-dd"); ????????System.out.println("get?static?method?the?SimpleDateFormat:"?+?df1); ????????try?{ ????????????return?df1.parse(str); ????????}?catch?(ParseException?e)?{ ????????????//?TODO?Auto-generated?catch?block ????????????e.printStackTrace(); ????????????return?null; ????????} ????} ????public?Date?printDateFormat(String?str)?{ ????????SimpleDateFormat?df2?=?new?SimpleDateFormat("yyyy-MM-dd"); ????????try?{ ????????????System.out.println("get?the?SimpleDateFormat:"?+?df2); ????????????return?df2.parse(str); ????????}?catch?(ParseException?e)?{ ????????????//?TODO?Auto-generated?catch?block ????????????e.printStackTrace(); ????????????return?null; ????????} ????} ????private?static?String?formatNumber(int?n)?{ ????????String?s?=?"0"?+?n; ????????return?s.substring(s.length()?-?2); ????} }
按照設想,應該是sdf打印出的對象是同一個,后面兩個打印出的對象因為每次需要新建對象,打印出來的都不相同才對。
但是結果如下:
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get static method the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
get the?SimpleDateFormat:java.text.SimpleDateFormat@f67a0200
get the?ReferenceDateFormat:java.text.SimpleDateFormat@f67a0200
對象居然是同一個,這就很奇怪了,誰知道原因呢?
看了下SimpleDateFormat源碼,里面根據pattern從static的concurrentHashMap中取對應的信息,對于不同的SimpleDateFormat對象,只要定義的格式相同,pattern對象是同一個。
后來換了種方式測試,直接粗暴的寫五個進程跑,證明確實會出現并發問題:
2018-12-25 2203-01-24
2498-10-10 2203-01-24
2018-12-25 0001-10-10
2998-01-02 3004-12-01
1698-09-22 3004-12-01
且只有共享的static會有這個問題,去掉共享的static,那么在方法內調用的就不存在并發問題。
/** ?*?TestDateFormat.java ?*?zhm.test.dateFormat ?*?2018年5月2日下午9:02:07 ?* ?*/ package?zhm.test.dateFormat; import?java.sql.Timestamp; import?java.text.ParseException; import?java.text.SimpleDateFormat; import?java.util.Calendar; import?java.util.Date; import?java.util.Random; /** ?*?@author?zhuheming?TestDateFormat?2018年5月2日下午9:02:07 ?*/ public?class?TestDateFormat?{ ????public?static?TestDateFormat?tdf?=?null; ????//SimpleDateFormat?sdf?=?new?SimpleDateFormat("yyyy-MM-dd"); ????public?static?void?main(String[]?args)?{ ????????tdf?=?new?TestDateFormat(); ????????????Thread?th2?=?new?Thread(new?Runnable()?{ ????????????????@Override ????????????????public?void?run()?{ ????????????????????while?(true)?{ ????????????????????????Random?r?=?new?Random(); ????????????????????????int?k?=?r.nextInt(100); ????????????????????????int?randomSwitch?=?k?%?3; ????????????????????????//Calendar?c?=?Calendar.getInstance(); ????????????????????????//c.add(Calendar.DATE,?k); ????????????????????????try?{ ????????????????????????????Thread.sleep(100); ????????????????????????????switch?(randomSwitch)?{ ????????????????????????????case?0: ????????????????????????????????String?s1?=?"2018-12-25"; ????????????????????????????????String?d1?=?tdf.printDateFormat(s1); ????????????????????????????????//String?d1?=?new?Timestamp(date1.getTime()).toString(); ????????????????????????????????//d1?=?d1.substring(0,d1.indexOf("?")); ????????????????????????????????if(!s1.equals(d1)){ ????????????????????????????????????System.out.println(s1+"?????"+d1); ????????????????????????????????} ????????????????????????????????break; ????????????????????????????case?1: ????????????????????????????????String?s2?=?"2018-12-25"; ????????????????????????????????String?d2?=?TestDateFormat.printStaticDateFormat(s2); ????????????????????????????????//String?d2?=?new?Timestamp(date2.getTime()).toString(); ????????????????????????????????//d2?=?d2.substring(0,d2.indexOf("?")); ????????????????????????????????if(!s2.equals(d2)){ ????????????????????????????????????System.out.println(s2+"?????"+d2); ????????????????????????????????} ????????????????????????????????break; ????????????????????????????case?2: ????????????????????????????????String?s?="2018-12-25"; ????????????????????????????????String?d3?=?tdf.printReferenceDateFormat(s); ????????????????????????????????//String?d3?=?new?Timestamp(date3.getTime()).toString(); ????????????????????????????????//d3?=?d3.substring(0,d3.indexOf("?")); ????????????????????????????????if(!s.equals(d3)){ ????????????????????????????????????System.out.println(s+"?????"+d3); ????????????????????????????????} ????????????????????????????????break; ????????????????????????????default: ????????????????????????????????return; ????????????????????????????} ????????????????????????}?catch?(Exception?e)?{ ????????????????????????} ????????????????????} ????????????????} ????????????}); ????Thread?th3?=?new?Thread(new?Runnable()?{ ????????@Override ????????public?void?run()?{ ????????????while?(true)?{ ????????????????Random?r?=?new?Random(); ????????????????int?k?=?r.nextInt(3); ????????????????int?randomSwitch?=?k?%?3; ????????????????//Calendar?c?=?Calendar.getInstance(); ????????????????//c.add(Calendar.DATE,?k); ????????????????try?{ ????????????????????Thread.sleep(100); ????????????????????switch?(randomSwitch)?{ ????????????????????case?0: ????????????????????????String?s1?=?"1998-11-12"; ????????????????????????String?d1?=?tdf.printDateFormat(s1); ????????????????????????//String?d1?=?new?Timestamp(date1.getTime()).toString(); ????????????????????????//d1?=?d1.substring(0,d1.indexOf("?")); ?????????????????????????if(!s1.equals(d1)){ ????????????????????????????System.out.println(s1+"?????"+d1); ?????????????????????????} ????????????????????????break; ????????????????????case?1: ????????????????????????String?s2?=?"1998-11-12"; ????????????????????????String?d2?=?TestDateFormat.printStaticDateFormat(s2); ????????????????????????//String?d2?=?new?Timestamp(date2.getTime()).toString(); ????????????????????????//d2?=?d2.substring(0,d2.indexOf("?")); ????????????????????????if(!s2.equals(d2)){ ????????????????????????????System.out.println(s2+"?????"+d2); ????????????????????????} ????????????????????????break; ????????????????????case?2: ????????????????????????String?s?=?"1998-11-12"; ????????????????????????String?d3?=?tdf.printReferenceDateFormat(s); ????????????????????????//String?d3?=?new?Timestamp(date3.getTime()).toString(); ????????????????????????//d3?=?d3.substring(0,d3.indexOf("?")); ????????????????????????if(!s.equals(d3)){ ????????????????????????????System.out.println(s+"?????"+d3); ????????????????????????} ????????????????????????break; ????????????????????default: ????????????????????????return; ????????????????????} ????????????????}?catch?(Exception?e)?{ ????????????????} ????????????} ????????} ????}); ????Thread?th4?=?new?Thread(new?Runnable()?{ ????????@Override ????????public?void?run()?{ ????????????while?(true)?{ ????????????????Random?r?=?new?Random(); ????????????????int?k?=?r.nextInt(3); ????????????????int?randomSwitch?=?k?%?3; ????????????????//Calendar?c?=?Calendar.getInstance(); ????????????????//c.add(Calendar.DATE,?k); ????????????????try?{ ????????????????????Thread.sleep(100); ????????????????????switch?(randomSwitch)?{ ????????????????????case?0: ????????????????????????String?s1?=?"1698-09-22"; ????????????????????????String?d1?=?tdf.printDateFormat(s1); ????????????????????????//String?d1?=?new?Timestamp(date1.getTime()).toString(); ????????????????????????//d1?=?d1.substring(0,d1.indexOf("?")); ?????????????????????????if(!s1.equals(d1)){ ????????????????????????????System.out.println(s1+"?????"+d1); ?????????????????????????} ????????????????????????break; ????????????????????case?1: ????????????????????????String?s2?=?"1698-09-22"; ????????????????????????String?d2?=?TestDateFormat.printStaticDateFormat(s2); ????????????????????????//String?d2?=?new?Timestamp(date2.getTime()).toString(); ????????????????????????//d2?=?d2.substring(0,d2.indexOf("?")); ????????????????????????if(!s2.equals(d2)){ ????????????????????????????System.out.println(s2+"?????"+d2); ????????????????????????} ????????????????????????break; ????????????????????case?2: ????????????????????????String?s?=?"1698-09-22"; ????????????????????????String?d3?=?tdf.printReferenceDateFormat(s); ????????????????????????//String?d3?=?new?Timestamp(date3.getTime()).toString(); ????????????????????????//d3?=?d3.substring(0,d3.indexOf("?")); ????????????????????????if(!s.equals(d3)){ ????????????????????????????System.out.println(s+"?????"+d3); ????????????????????????} ????????????????????????break; ????????????????????default: ????????????????????????return; ????????????????????} ????????????????}?catch?(Exception?e)?{ ????????????????} ????????????} ????????} ????}); ????Thread?th5?=?new?Thread(new?Runnable()?{ ????????@Override ????????public?void?run()?{ ????????????while?(true)?{ ????????????????Random?r?=?new?Random(); ????????????????int?k?=?r.nextInt(3); ????????????????int?randomSwitch?=?k?%?3; ????????????????//Calendar?c?=?Calendar.getInstance(); ????????????????//c.add(Calendar.DATE,?k); ????????????????try?{ ????????????????????Thread.sleep(100); ????????????????????switch?(randomSwitch)?{ ????????????????????case?0: ????????????????????????String?s1?=?"2498-10-10"; ????????????????????????String?d1?=?tdf.printDateFormat(s1); ????????????????????????//String?d1?=?new?Timestamp(date1.getTime()).toString(); ????????????????????????//d1?=?d1.substring(0,d1.indexOf("?")); ?????????????????????????if(!s1.equals(d1)){ ????????????????????????????System.out.println(s1+"?????"+d1); ?????????????????????????} ????????????????????????break; ????????????????????case?1: ????????????????????????String?s2?=?"2498-10-10"; ????????????????????????String?d2?=?TestDateFormat.printStaticDateFormat(s2); ????????????????????????//String?d2?=?new?Timestamp(date2.getTime()).toString(); ????????????????????????//d2?=?d2.substring(0,d2.indexOf("?")); ????????????????????????if(!s2.equals(d2)){ ????????????????????????????System.out.println(s2+"?????"+d2); ????????????????????????} ????????????????????????break; ????????????????????case?2: ????????????????????????String?s?=?"2498-10-10"; ????????????????????????String?d3?=?tdf.printReferenceDateFormat(s); ????????????????????????//String?d3?=?new?Timestamp(date3.getTime()).toString(); ????????????????????????//d3?=?d3.substring(0,d3.indexOf("?")); ????????????????????????if(!s.equals(d3)){ ????????????????????????????System.out.println(s+"?????"+d3); ????????????????????????} ????????????????????????break; ????????????????????default: ????????????????????????return; ????????????????????} ????????????????}?catch?(Exception?e)?{ ????????????????} ????????????} ????????} ????}); ????Thread?th6?=?new?Thread(new?Runnable()?{ ????????@Override ????????public?void?run()?{ ????????????while?(true)?{ ????????????????Random?r?=?new?Random(); ????????????????int?k?=?r.nextInt(3); ????????????????int?randomSwitch?=?k?%?3; ????????????????//Calendar?c?=?Calendar.getInstance(); ????????????????//c.add(Calendar.DATE,?k); ????????????????try?{ ????????????????????Thread.sleep(100); ????????????????????switch?(randomSwitch)?{ ????????????????????case?0: ????????????????????????String?s1?=?"2998-01-02"; ????????????????????????String?d1?=?tdf.printDateFormat(s1); ????????????????????????//String?d1?=?new?Timestamp(date1.getTime()).toString(); ????????????????????????//d1?=?d1.substring(0,d1.indexOf("?")); ?????????????????????????if(!s1.equals(d1)){ ????????????????????????????System.out.println(s1+"?????"+d1); ?????????????????????????} ????????????????????????break; ????????????????????case?1: ????????????????????????String?s2?=?"2998-01-02"; ????????????????????????String?d2?=?TestDateFormat.printStaticDateFormat(s2); ????????????????????????//String?d2?=?new?Timestamp(date2.getTime()).toString(); ????????????????????????//d2?=?d2.substring(0,d2.indexOf("?")); ????????????????????????if(!s2.equals(d2)){ ????????????????????????????System.out.println(s2+"?????"+d2); ????????????????????????} ????????????????????????break; ????????????????????case?2: ????????????????????????String?s?=?"2998-01-02"; ????????????????????????String?d3?=?tdf.printReferenceDateFormat(s); ????????????????????????//String?d3?=?new?Timestamp(date3.getTime()).toString(); ????????????????????????//d3?=?d3.substring(0,d3.indexOf("?")); ????????????????????????if(!s.equals(d3)){ ????????????????????????????System.out.println(s+"?????"+d3); ????????????????????????} ????????????????????????break; ????????????????????default: ????????????????????????return; ????????????????????} ????????????????}?catch?(Exception?e)?{ ????????????????} ????????????} ????????} ????}); ????th2.start(); ????th3.start(); ????th4.start(); ????th5.start(); ????th6.start(); ????try?{ ????????th2.join(); ????????th3.join(); ????????th4.join(); ????????th5.join(); ????????th6.join(); ????}?catch?(InterruptedException?e)?{ ????????//?TODO?Auto-generated?catch?block ????????e.printStackTrace(); ????} } ????public?String?printReferenceDateFormat(String?str)?{ ????????//Date?dt=?sdf.parse(str); ????????//return?sdf.format(dt); ????????return?str; ????} ????public?static?String?printStaticDateFormat(String?str)?{ ????????SimpleDateFormat?df1?=?new?SimpleDateFormat("yyyy-MM-dd"); ????????//System.out.println("get?static?method?the?SimpleDateFormat:"?+?df1); ????????try?{ ????????????Thread.sleep(100); ????????????Date?dt=df1.parse(str); ????????????str=df1.format(dt); ????????????//df1.getCalendar().clear(); ????????????return?str; ????????}?catch?(Exception?e)?{ ????????????//?TODO?Auto-generated?catch?block ????????????e.printStackTrace(); ????????????return?null; ????????} ????} ????public?String?printDateFormat(String?str)?{ ????????SimpleDateFormat?df2?=?new?SimpleDateFormat("yyyy-MM-dd"); ????????try?{ ????????????Thread.sleep(100); ????????????Date?dt=df2.parse(str); ????????????str=df2.format(dt); ????????????//df2.getCalendar().clear(); ????????????//System.out.println("get?the?SimpleDateFormat:"?+?df2); ????????????return?str; ????????}?catch?(Exception?e)?{ ????????????//?TODO?Auto-generated?catch?block ????????????e.printStackTrace(); ????????????return?null; ????????} ????} }
從結果來看,確實不是同一個對象,只是看起來像。
那么只有最后一個問題了,為什么看起來是同一個對象呢:
元芳,你怎么看?
大人,屬下這樣認為:
大家都知道system.out.prinl(object)其實是打印的String.valueof的對象值;valueof是什么呢?
public?static?String?valueOf(Object?obj)?{? ????return?(obj?==?null)???“null”?:?obj.toString();? }
就是obj的toString的值,那么obj的toString由Object類定義,各個子類自己重寫,在Object中,定義如下:
public?String?toString()?{? ????return?getClass().getName()?+?“@”?+?Integer.toHexString(hashCode());? }
顯然就是Object的hashCode的十六進制數值,那么在SimpleDateFormat中hashcode方法是如何呢
public?int?hashCode()? {? ????return?pattern.hashCode();? ????//?just?enough?fields?for?a?reasonable?distribution? }
從這里可以看出,SimpleDateFormat沒有返回自己的對象的地址等,而是返回了pattern的hashcode,前面已經說過,輸入的格式相同,pattern是同一個,所以,此處SimpleDateFormat對象打印出來是同一個,但其實不是。
狄仁杰:元芳,我這個宰相的位置,以后要不你來做吧。。。
-----------------結束的分割線-----------------
之前我寫在CSDN上的文章,搬到平臺上來:
如果覺得不錯,請贊咱一下唄
原文鏈接:https://blog.csdn.net/qq_35039122/article/details/80172714
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。