1.背景
final這個關鍵字相信大家不陌生吧...
看看下面的案例
2.時間格式化之線程不安全SimpleDateFormat
package com.ldp.demo08final; import lombok.extern.slf4j.Slf4j; import java.text.ParseException; import java.text.SimpleDateFormat; /** * @author 姿勢帝-博客園 * @address https://www.cnblogs.com/newAndHui/ * @WeChat 851298348 * @create 02/19 7:37 * @description */ @Slf4j public class Test01SimpleDateFormat { /** * 在併發的情況下可能會拋出如下異常: * Exception in thread "t-3" java.lang.NumberFormatException: For input string: "" * at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65) * at java.lang.Long.parseLong(Long.java:601) * at java.lang.Long.parseLong(Long.java:631) * at java.text.DigitList.getLong(DigitList.java:195) * at java.text.DecimalFormat.parse(DecimalFormat.java:2051) * at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1869) * at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514) * at java.text.DateFormat.parse(DateFormat.java:364) * at com.ldp.demo08final.Test01Time.lambda$main$0(Test01Time.java:22) * at java.lang.Thread.run(Thread.java:748) * * @param args */ public static void main(String[] args) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); for (int i = 0; i < 20; i++) { new Thread(() -> { try { log.info("日期爲:{}", format.parse("2022-02-02")); } catch (ParseException e) { e.printStackTrace(); } }, "t-" + i).start(); } } }
3.時間格式化之加鎖實現線程安全
package com.ldp.demo08final; import lombok.extern.slf4j.Slf4j; import java.text.ParseException; import java.text.SimpleDateFormat; /** * @author 姿勢帝-博客園 * @address https://www.cnblogs.com/newAndHui/ * @WeChat 851298348 * @create 02/19 7:37 * @description * * <p> * 在併發的情況下可能會拋出如下異常: * Exception in thread "t-3" java.lang.NumberFormatException: For input string: "" * 解決方案: * 1.加鎖 * 2.不可變的思維 * </p> */ @Slf4j public class Test02SimpleDateFormat { /** * 加鎖synchronized 的方式解決併發問題 * * @param args */ public static void main(String[] args) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); for (int i = 0; i < 20; i++) { new Thread(() -> { synchronized (format) { try { log.info("日期爲:{}", format.parse("2022-02-02")); } catch (ParseException e) { e.printStackTrace(); } } }, "t-" + i).start(); } } }
4.時間格式化之DateTimeFormatter線程安全
package com.ldp.demo08final; import lombok.extern.slf4j.Slf4j; import java.time.format.DateTimeFormatter; /** * @author 姿勢帝-博客園 * @address https://www.cnblogs.com/newAndHui/ * @WeChat 851298348 * @create 02/19 7:49 * @description */ @Slf4j public class Test03DateTimeFormatter { /** * 不可變的特性解決併發情況下的線程安全問題 * * @param args */ public static void main(String[] args) { // @since 1.8 DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy-MM-dd"); for (int i = 0; i < 20; i++) { new Thread(() -> { try { log.info("日期爲:{}", format.parse("2022-02-02")); } catch (Exception e) { e.printStackTrace(); } }, "t-" + i).start(); } } }
5.String對象中使用源碼的理解
package com.ldp.demo08final; import org.junit.Test; /** * @author 姿勢帝-博客園 * @address https://www.cnblogs.com/newAndHui/ * @WeChat 851298348 * @create 02/19 7:59 * @description <p> * 這一節我們來看看String源碼 * 1.final 關鍵字 * 發現String類、類中所有屬性多是 final 的 * 屬性用 final 修飾保證了該屬性是隻讀的,不能修改 * 類用 final 修飾保證了該類中的方法不能被覆蓋,防止子類無意間破壞不可變性 * <p> * 2.substring方法保護性拷貝 * * </p> */ public class Test04String { private String name = "final"; /** * public String substring(int beginIndex) { * if (beginIndex < 0) { * throw new StringIndexOutOfBoundsException(beginIndex); * } * int subLen = value.length - beginIndex; * if (subLen < 0) { * throw new StringIndexOutOfBoundsException(subLen); * } * return (beginIndex == 0) ? this : new String(value, beginIndex, subLen); * } */ @Test public void test01Substring() { String substring = name.substring(2); System.out.println(substring); } }
完美!