JAVA face questions the difference between StringBuffer and StringBuilder analyzed from the perspective of the source?

Interviewer Q1: Will the StringBuffer and StringBuilder What is the difference?

This is a common theme, each interview will be asked a few years ago I, as a basis for interview questions, asked about the probability of ninety eight percent. Now we need from A to interview several knowledge points to sum up the difference between the two is what?

  • Inheritance?

  • How to achieve the expansion?

  • Thread safety?

 

Inheritance

Take a look at the structure of class inheritance and StringBuffer StringBuilder from the source:

 

From the structural view can be up to, StringBuffer StringBuiler and are inherited from the class AbstractStringBuilder

 

How to achieve expansion

Mechanisms StringBuffer and StringBuiler expansion implemented in the abstract class AbstractStringBuilder in (the default length is 16), will be automatically expansion work when discovered not long enough when extended to the original array length of 2 doubly 2, create a new array, and copy the data array into a new array.

void the ensureCapacity public (the minimumCapacity int) { 
    IF (the minimumCapacity> 0) 
        ensureCapacityInternal (the minimumCapacity); 
} 

/ ** 
. * value to ensure that the character array again without crossing a new array of references to value 
* /     
Private void ensureCapacityInternal (int the minimumCapacity) { 
    Conscious overflow-code // 
    IF (the minimumCapacity - value.length> 0) { 
        value = Arrays.copyOf (value, 
                newCapacity (the minimumCapacity)); 
    } 
} 

/ ** 
* expansion: the extended length of 2 times the size before +2 
* /     
Private int newCapacity (int minCapacity) { 
    // overflow code-Conscious expanded twice +2 
    // here may overflow, overflow is negative Kazakhstan, attention 
    int newCapacity = (value.length <<. 1) + 2;
    IF (newCapacity - be minCapacity <0) { 
        newCapacity be minCapacity =; 
    } 
    // MAX_ARRAY_SIZE values are Integer.MAX_VALUE - 8, to determine what the expected capacity (newCapacity) is between 0 <x <MAX_ARRAY_SIZE, directly in this section the return value, which does not go to determine what interval an overflow 
    return (newCapacity <= 0 || MAX_ARRAY_SIZE - newCapacity <0) 
        hugeCapacity (be minCapacity)? 
        : newCapacity; 
} 

/ ** 
* size is determined whether the overflow 
* / 
Private int hugeCapacity (int be minCapacity) { 
    IF (Integer.MAX_VALUE - be minCapacity <0) {// overflow 
        the throw an OutOfMemoryError new new (); 
    } 
    return (be minCapacity> MAX_ARRAY_SIZE)  
        be minCapacity: MAX_ARRAY_SIZE? ;
}

 

Thread safety

Let's take a look at the relevant methods of StringBuffer:

@Override
public synchronized StringBuffer append(long lng) {
    toStringCache = null;
    super.append(lng);
    return this;
}

/**
 * @throws StringIndexOutOfBoundsException {@inheritDoc}
 * @since      1.2
 */
@Override
public synchronized StringBuffer replace(int start, int end, String str) {
    toStringCache = null;
    super.replace(start, end, str);
    return this;
}

/**
 * @throws StringIndexOutOfBoundsException {@inheritDoc}
 * @since      1.2
 */
@Override
public synchronized String substring(int start) {
    return substring(start, count);
}

@Override
public synchronized String toString() {
    if (toStringCache == null) {
        toStringCache = Arrays.copyOfRange(value, 0, count);
    }
    return new String(toStringCache, true);
}

From the above code, we see that almost all methods are added synchronized, the parent class almost always invoked., Modified with the synchronized keyword means what? Lock, synchronous serial processing resources, so it is thread-safe.

 

We look at the relevant source StringBuilder:

@Override
public StringBuilder append(double d) {
    super.append(d);
    return this;
}

/**
 * @since 1.5
 */
@Override
public StringBuilder appendCodePoint(int codePoint) {
    super.appendCodePoint(codePoint);
    return this;
}

/**
 * @throws StringIndexOutOfBoundsException {@inheritDoc}
 */
@Override
public StringBuilder delete(int start, int end) {
    super.delete(start, end);
    return this;
}

StringBuilder source inside, basically all methods are not modified with the synchronized keyword, when multi-threaded access, there will be thread-safety issues.

 

To prove thread-safe StringBuffer, StringBuilder thread-safe, we verified by a piece of code:

Test Ideas

  • Were written StringBuffer and StringBuilder with 1000 threads,

  • Use CountDownLatch ensure that only print StringBuffer and StringBuilder length after their 1000 threads executed,

  • Observation results.

Test code

import java.util.concurrent.CountDownLatch;

public class TestStringBuilderAndStringBuffer {
    public static void main(String[] args) {
        //证明StringBuffer线程安全,StringBuilder线程不安全
        StringBuffer stringBuffer = new StringBuffer();
        StringBuilder stringBuilder = new StringBuilder();
        CountDownLatch latch1 = new CountDownLatch(1000);
        CountDownLatch latch2 = new CountDownLatch(1000);
        for (int i = 0; i < 1000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        stringBuilder.append(1);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        latch1.countDown();
                    }
                }
            }).start();
        }
        for (int i = 0; i < 1000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        stringBuffer.append(1);
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        latch2.countDown();
                    }

                }
            }).start();
        }
        try {
            latch1.await();
            System.out.println(stringBuilder.length());
            latch2.await();
            System.out.println(stringBuffer.length());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Test Results

  • No matter how many times StringBuffer run length is 1000.

  • The vast majority are StringBuilder when the length is less than 1000.

  • Thread-safe StringBuffer, StringBuilder thread-unsafe proven.

in conclusion

  • StringBuffer and StringBuilder are inherited from the abstract class AbstractStringBuilder.

  • Character array to store data has not been modified final, that values ​​can be changed, and constructed a string of vacant position as well as string concatenation, but certainly there is a time stitching down enough, and this time they have provided an automatic internal expansion mechanism (the default length is 16) will automatically discover when the length is not enough time expansion work, create a new extension of the array is doubly 2 2 of the original length of the array, and copy the data array into a new array, so for stitching string string higher than the efficiency. Automatic expansion mechanism is implemented in the abstract class.

  • Thread safety: StringBuffer low efficiency, thread-safe, because many StringBuffer methods are synchronized modified, and when multi-threaded access, thread-safe, but inefficient, because it has a lock and release the lock process. StringBuilder efficiency is high, but the thread is unsafe.

 

Old iron if you have any other answer, can Comments Ha!

 

Guess you like

Origin www.cnblogs.com/marsitman/p/11204313.html