Java中的String、StringBuffer和StringBuilder

Java中的String、StringBuffer和StringBuilder

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

线程不安全就是不提供数据访问保护,有可能出现多个线程先后更改数据造成所得到的数据是脏数据。

java.lang.String

不可变,final类,不允许被继承,给String 变量重新赋值相当于重新生成一个新的String 类型对象,原对象会根据GC规则进行回收。

java.lang.StringBuffer

线程安全的可变字符序列,适用于多线程程序,保证同步性

java.lang.StringBuilder

非线程安全的可变字符序列,Java SE 5 引入,适用于单线程程序,不保证同步性,相比于 StringBuffer 开销较小

class CustomThread extends Thread {
    private StringBuffer buffer;
    private StringBuilder builder;

    public CustomThread(StringBuffer buffer, StringBuilder builder) {
        this.buffer = buffer;
        this.builder = builder;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            buffer.append("A");
            builder.append("Z");
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("StringBuffer Size:" + buffer.length() 
            + " | "
            + "StringBuilder Size:" + builder.length());
    }
}

public static void main(String[] args) {
    StringBuffer buffer = new StringBuffer();
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < 10; i++) {
        new CustomThread(buffer, builder).start();
    }
}

1

最终结果StringBuffer的大小总会达到10000,而StringBuilder的大小不一定会达到10000,而值未知。

String 和 StringBuffer 比较

通常情况下 StringBuffer 性能优于 String。

StringBuffer 是线程安全的可变字符序列,类似于 String 的字符串缓冲区,可以修改。

虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。

append 方法始终将这些字符添加到缓冲区的末端

insert 方法则在指定的点添加字符。

StringBuffer 和 StringBuilder 比较

通常情况下 StringBuilder 性能优于 StringBuffer。

StringBuilder 是 Java SE 5 新增的非线程安全可变字符序列,提供与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。

建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。

public void test() {
    long start = 0;
    long end = 0;

    int cycleTimes = 10000;
    String str = "";
    start = System.currentTimeMillis();
    for (int i = 0; i < cycleTimes; i++) {
        str = str + i;
    }
    end = System.currentTimeMillis();
    System.out.println("String::" + (end - start));

    StringBuffer strBuffer = new StringBuffer();
    start = System.currentTimeMillis();
    for (int i = 0; i < cycleTimes; i++) {
        strBuffer.append(i);
    }
    end = System.currentTimeMillis();
    System.out.println("StringBuffer::" + (end - start));

    StringBuilder strBuilder = new StringBuilder();
    start = System.currentTimeMillis();
    for (int i = 0; i < cycleTimes; i++) {
        strBuilder.append(i);
    }
    end = System.currentTimeMillis();
    System.out.println("StringBuilder::" + (end - start));
}

从测试结果可以看出,String 与 StringBuffer、StringBuilder 性能差距非常明显,但是 StringBuffer 和 StringBuilder 性能差距不明显,可以通过增大循环次数测试 StringBuffer 和 StringBuilder 性能差距。

修改单元测试比较 StringBuffer 和 StringBuilder 性能差距

public class Main {

    public static void main(String[] args) {
        test();
    }
    private static void test() {
        long start = 0;
        long end = 0;

        int cycleTimes = 1000000;

        StringBuffer strBuffer = new StringBuffer();
        start = System.currentTimeMillis();
        for (int i = 0; i < cycleTimes; i++) {
            strBuffer.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println("StringBuffer::" + (end - start));

        StringBuilder strBuilder = new StringBuilder();
        start = System.currentTimeMillis();
        for (int i = 0; i < cycleTimes; i++) {
            strBuilder.append(i);
        }
        end = System.currentTimeMillis();
        System.out.println("StringBuilder::" + (end - start));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值