java多線程之-不可變final

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();
        }
    }
}
View Code

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();
        }
    }
}
View Code

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();
        }
    }
}
View Code

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

 

完美!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章