开发制作一个网站,容桂品牌网站建设,用php做的订票网站,西安专业网站设计StringBuilder和StringBuffer的用法是一致的#xff0c;平常我们最多用到的方法就是append()拼接字符串和reverse()翻转字符串等等。二者看起来方法是一样的#xff0c;确实也是这样#xff0c;其实它俩唯一的不同在于StringBuilder不是线程安全的#xff0c;而StringBuffe… StringBuilder和StringBuffer的用法是一致的平常我们最多用到的方法就是append()拼接字符串和reverse()翻转字符串等等。二者看起来方法是一样的确实也是这样其实它俩唯一的不同在于StringBuilder不是线程安全的而StringBuffer则是线程安全的。 证明如下
验证StriingBuilder
我们分别用两个线程对同一StringBuilder对象追加不同的字符查看结果
public static void main(String[] args) throws InterruptedException {StringBuilder builder new StringBuilder();StringBuffer buffer new StringBuffer();Thread t1 new Thread(new Runnable() {Overridepublic void run() {for (int i 0; i 1000; i) {builder.append(A);}}});Thread t2 new Thread(new Runnable() {Overridepublic void run() {for (int i 0; i 1000; i) {builder.append(B);}}});t1.start();t2.start();t1.join();t2.join();System.out.println(builder.toString());}
结果 我们发现线程1追加字符‘a’运行得好好的突然线程2追加字符‘b’也加了进来两个线程轮流对StringBuilder对象进行操作 此外还发生了下标越界的报错可能是因为两个线程在争夺资源的时候发生的错误毕竟StringBuilder的底层其实是一个char数组线程 A 想要在位置 i 插入字符而线程 B 想要在相同的位置 i 插入不同的字符。这将导致一个或者两个操作执行失败或者得到错误结果。所以运行结果中不只有AB两种字符还有一个类似乱码的字符 结论StringBuilder不是线程安全的
验证StringBuffer
验证方法和上面一直我们分别用两个线程对同一StringBuffer对象追加不同的字符查看结果
public static void main(String[] args) throws InterruptedException {StringBuilder builder new StringBuilder();StringBuffer buffer new StringBuffer();Thread t1 new Thread(new Runnable() {Overridepublic void run() {for (int i 0; i 1000; i) {buffer.append(A);}}});Thread t2 new Thread(new Runnable() {Overridepublic void run() {for (int i 0; i 1000; i) {buffer.append(B);}}});t1.start();t2.start();t1.join();t2.join();System.out.println(buffer.toString());} 结果 我们发现尽管是两个线程但是并没有因为抢占公共资源同一个StringBuffer对象而交替执行而是很丝滑快速的执行完成更没有报错。 结论StringBuffer是线程安全的
总结
两个线程同时操作同一个 StringBuilder 对象如果没有采取合适的同步机制那么就会出现下标越界的错误。
在多线程环境下由于线程调度是不可控的两个线程可能同时访问同一个 StringBuilder 对象并且同时调用 append() 或 insert() 等方法进行修改操作。由于 StringBuilder 不是线程安全的类在并发访问时可能会出现以下问题
1. 竞态条件如果两个线程在同一时间进行 append() 或 insert() 操作则可能会导致竞态条件。例如线程 A 想要在位置 i 插入字符而线程 B 想要在相同的位置 i 插入不同的字符。这将导致一个或者两个操作执行失败或者得到错误结果。
2. 内存可见性如果两个线程分别持有 StringBuilder 的不同实例并且每个实例都缓存了修改后的值则另一个线程可能无法看到这些更改因此应该使用 volatile 关键字保证内存可见性。
综上所述为了避免 StringBuilder 下标越界错误和其他多线程问题需要采取合适的同步机制来保证对 StringBuilder 的访问是互斥、有序和可见的。例如可以使用 synchronized 来锁住StringBuilder对象或者使用 ConcurrentLinkedQueueStringBuilder 之类的线程安全容器来避免竞争条件。 因此当我们今后使用的时候需要注意场景。如果是比如多线程爬虫将爬到的内容拼接在一起的话需要使用StringBuffer而一般单线程的情况下可以使用StringBuilder。