JUC concurrent programming - Advanced 06 - immutability of sharing model (design of immutable classes | use of immutable classes | sharing meta mode)

6, Immutability of shared model

Contents of this chapter

  • Use of immutable classes
  • Immutable class design
  • Stateless class design

6.1 date conversion

1. Questions raised

The following code is not thread safe at run time because SimpleDateFormat

private static void test01() {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            try {
                log.debug("{}", sdf.parse("1951-04-21"));
            } catch (Exception e) {
                log.error("{}", e);
            }
        }).start();
    }
}

There is a high probability of java.lang.NumberFormatException or incorrect date resolution results, such as:

12:02:00.338 c.Test1 [Thread-2] - {}
java.lang.NumberFormatException: empty String
	at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
	at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
	at java.lang.Double.parseDouble(Double.java:538)
	at java.text.DigitList.getDouble(DigitList.java:169)
	at java.text.DecimalFormat.parse(DecimalFormat.java:2089)
	at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
	at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
	at java.text.DateFormat.parse(DateFormat.java:364)
	at cn.itcast.n7.Test1.lambda$test01$1(Test1.java:31)
	at java.lang.Thread.run(Thread.java:748)
12:02:00.338 c.Test1 [Thread-0] - {}
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:2084)
	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 cn.itcast.n7.Test1.lambda$test01$1(Test1.java:31)
	at java.lang.Thread.run(Thread.java:748)
12:02:00.337 c.Test1 [Thread-6] - Fri Apr 21 00:00:00 CST 1195
12:02:00.337 c.Test1 [Thread-4] - Fri Apr 21 00:00:00 CST 1195
12:02:00.337 c.Test1 [Thread-7] - Sat Apr 21 00:00:00 CST 1951
12:02:00.337 c.Test1 [Thread-8] - Sat Apr 21 00:00:00 CST 1951
12:02:00.337 c.Test1 [Thread-5] - Fri Apr 21 00:00:00 CST 1195
12:02:00.337 c.Test1 [Thread-9] - Sat Apr 21 00:00:00 CST 1951
12:02:00.337 c.Test1 [Thread-3] - Fri Apr 21 00:00:00 CST 1195
12:02:00.337 c.Test1 [Thread-1] - Fri Apr 21 00:00:00 CST 1195

2. Idea - synchronous lock

3. Ideas - immutable
If an object cannot modify its internal state (properties), then it is thread safe, because there is no concurrent modification! There are many such objects in Java. For example, after Java 8, a new date formatting class is provided:

public static void test02() {
    DateTimeFormatter stf = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    for (int i = 0; i < 10; i++) {
        new Thread(() -> {
            TemporalAccessor parse = stf.parse("1951-04-21");
            log.debug("{}", parse);
        }).start();
    }
}

You can see the source code of DateTimeFormatter

6.2 immutable design

6.2.1 design of string class

Another more familiar String class is also immutable. Take it as an example to illustrate the elements of immutable design

public final class String
    implements java.io.Serializable, Comparable<String>, CharSequence {
    /** The value is used for character storage. */
    private final char value[];

    /** Cache the hash code for the string */
    private int hash; // Default to 0
    
    // ...
}

1. Use of final

It is found that the class and all attributes in the class are final

  • The attribute is decorated with final to ensure that the attribute is read-only and cannot be modified
  • Class is decorated with final to ensure that the methods in this class cannot be overwritten and prevent subclasses from inadvertently destroying immutability

2. Protective copy

However, some students will say that when using strings, there are also some methods related to modification, such as substring. Let's take substring as an example to see how these methods are implemented:

public String substring(int beginIndex) {
    //Conduct verification
    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);
}

It is found that the constructor of String is called to create a new String, and then enter this constructor to see whether the final char[] value has been modified:

public String(char value[], int offset, int count) {
    if (offset < 0) {
        throw new StringIndexOutOfBoundsException(offset);
    }
    if (count <= 0) {
        if (count < 0) {
            throw new StringIndexOutOfBoundsException(count);
        }
        if (offset <= value.length) {
            this.value = "".value;
            return;
        }
    }
    // Note: offset or count might be near -1>>>1.
    if (offset > value.length - count) {
        throw new StringIndexOutOfBoundsException(offset + count);
    }
    //Copy generates a new array
    this.value = Arrays.copyOfRange(value, offset, offset+count);
}

It was found that neither. When constructing a new string object, a new char[] value will be generated to copy the content. This means of avoiding sharing by creating replica objects is called [protective copy]

*Enjoy the yuan of mode

reference resources "JUC concurrent programming - mode" protective pause mode | sequence control mode | producer consumer mode | two-stage termination mode | Balking mode | sharing mode

Principle final

6.3 stateless

When learning in the web stage, in order to ensure its thread safety when designing servlets, there will be such suggestions. Do not set member variables for servlets. Such classes without any member variables are thread safe

Because the data saved by member variables can also be called status information, it is called stateless if there is no member variable

difference

  • Immutable: it has members and states, but it cannot be changed. It is thread safe
  • Stateless: no member, stateless, immutable Lou, thread safe

Summary of this chapter

Use of immutable classes

Immutable class design

  • Principle aspect
    • final
  • Mode aspect
    • Enjoy yuan

Tags: Java Concurrent Programming

Posted by msimonds on Wed, 10 Aug 2022 22:02:36 +0530