StringBuffer and StringBuilder The StringBuilder Why not thread-safe

What is the difference in StringBuffer and StringBuilder?

StringBuffer is thread-safe, StringBuilder is not thread-safe.

So where StringBuilder insecurity in? Before thinking about this question, we need to know the internal StringBuffer and StringBuilder implementation and the String class is the same, all through a char array to store the string, except that the char array String class is final modified, it is immutable; but StringBuffer and StringBuilder char array is variable.

example:

Multithreading StringBuilder object

 1 public class StringBuilderDemo{
 2     public static void main(String[] args) throws InterruptedException{
 3         StringBuilder sBuilder = new StringBuilder();
 4         for(int i=0;i<10;i++){
 5             new Thread(new Runnable(){
 6                 @Override
 7                 public void run(){
 8                     for(int j=0;j<1000;j++){
 9                         sBuilder.append("a");
10                     }
11                 }
12             }).start();
13         }
14         Thread.sleep(100);
15         System.out.println(sBuilder.length());
16     }
17 }

 

operation result

7346

This creates 10 threads, each 1000 cycles StringBuilder object to append a character in normal circumstances should output 10000; but the results are less than expected results, may also throw an exception "ArrayIndexOutOfBoundsException" in actual operation

So, the question is, why is not the same as the expected output value? Why throw an exception "ArrayIndexOutOfBoundsException"?

Look at the first question:

Two member variables of StringBuilder (these two variables defined in AbstractStringBuilder inside, StringBuilder and StringBuffer have inherited AbstractStringBuilder)

// specific content stored string 
char [] value;
 // number of characters have been used in arrays 
int COUNT;

Looking at the StringBuilder append () method

@Override
public StringBuilder append(String str){
    super.append(str);
    return this;
}

The StringBuilder append () method call AbstractStringBuilder the append () method

 1 public AbstractStringBuilder append(String str){
 2     if(str==null){
 3         return appendNull();
 4     }
 5     int len = str.length();
 6     ensureCapacityInternal(count + len);
 7     str.getChars(0,len,value,count);
 8     count += len;
 9     return this;
10 }

See eighth row, count + = len; count of 10 is assumed, len is 1, two threads simultaneously performed here, to get the count values ​​are 10, after executing an addition operation after the value assigned to the count, two results the reason count thread after the implementation of the value of 11, rather than 12, which is the output value is smaller than the expected value.

Second question

Looking back at AbstractStringBuilder the append () method on line 6

ensureCapacityInternal () method is to check the StringBuilder () the original capacity of the char array object can hold the new string, if the fit is called expandCapacity () method char array expansion

private void ensureCapacityInternal(int minimumCapacity){
    if(minimumCapacity - value.length>0)
        expandCapacity(minimumCapacity);
}

That is a new expansion of a new char array, in the original copy of the contents of the array to the new array, and finally a pointer to a new char array

void expandCapacity ( int minimunCapacity) {
     // calculate the new capacity 
    int newCapacity value.length = 2 * + 2 ;
     // omit some check logic 
    ... 
    value = Array.copyOf (value, newCapacity); 
}
Array.copyOf () method
public static char[] copyOf(char[] original,int newLength){
    char[] copy = new char[newLength];
    //拷贝数组
    System.arraycopy(original,0,copy,0,Mathmin(original.length,newLength));
    return copy;
}

AbstractStringBuilder the append () method at line 7, an array of char content is copied to the String object array char object inside StringBuilder

 str.getChars(0,len,value,count);

getChars () method

public void getChars(int srcBegin,int srcEnd,char dst[],int dstBegin){
    //
    ...
    System.arraycopy(value,srcBegin,dst,dstBegin,srcEnd-srcBegin);
}

 

Copy process:

Suppose there are two methods of threads simultaneously executed StringBuilder append () method, two threads are executed over ensureCapacityInternal (), this time count = 5

At this time cpu time slot the thread 1 runs out, continue to thread 2, the thread 2 executes End append () method becomes 6

Get value 1 when the thread continues str, getChars () method is 6, when executed copy of char array will throw an exception ArrayIndexOutOfBoundsException.

Interpretation is completed!

They will replace the StringBuffer StringBuilder what will happen then?

But a thread-safe StringBuffer StringBuffer, of course, is the output of 10 000 friends.

 

Guess you like

Origin www.cnblogs.com/jaci/p/11450711.html