辽宁省建设工程信息网32位浏览器,贵阳网站优化排名,市场营销策划方案格式模板,开网站的宣传图片怎么做目录 1.String
2.StringBuffer
3.StringBuilder
4.线程安全的验证 1.String
String是声明在java.lang下的一个类。
String被定义为final#xff0c;表示不能被继承。内部定义了final char value[]用于存储字符串数据#xff0c;所以String对象的值是不可改变的。每次对S…目录 1.String
2.StringBuffer
3.StringBuilder
4.线程安全的验证 1.String
String是声明在java.lang下的一个类。
String被定义为final表示不能被继承。内部定义了final char value[]用于存储字符串数据所以String对象的值是不可改变的。每次对String对象操作都会生成新的String对象效率低并且会浪费大量的内存空间。
String实现了Serializable接口说明是支持序列化的。
String在底层存储时是存储在字符数组中的。 Testpublic void test1() {// 例1String str1 123;System.out.println(System.identityHashCode(str1));str1 369;System.out.println(System.identityHashCode(str1));// 例2String str2 456;System.out.println(System.identityHashCode(str2));String str3 456;System.out.println(System.identityHashCode(str3));// 例3String str4 258;System.out.println(System.identityHashCode(str4));String str5 new String(258);System.out.println(System.identityHashCode(str5));}// 结果
1724731843
1305193908
1313953385
1313953385
399573350
463345942 如例1所示str1赋值之后再次修改修改前后内存地址发生了改变并不是直接改变了值而是重新开辟内存空间存储新的值str1指定最新的内存地址。因而会占用两部分内存空间之前占用的内存并不会立即释放修改前后的地址不一致。
如例2所示str2赋值之后会在常量池中占用内存在栈中的引用变量指向常量池的内存地址常量池中存在之后相同的值不会再次开辟内存空间存储直接会在返回现有的内存地址。str2和str3的内存地址是一致的。
如例3所示使用new方式定义的String对象会在堆中开辟内存空间来存储在栈中创建引用变量指定堆内存中地址因而虽然strs4和str5的值是一致的但是在内存中的存储位置是不一致的。
使用String类的一些替换及拼接方法等都是会生成新的对象而不是对原有对象的修改。
2.StringBuffer
StringBuffer是对String的一个改进。 因为String的不可变性导致每次对字符串进行更改操作时都会重新赋值效率低下。 StringBuffer是可变的字符序列是线程安全的。底层也是使用字符数组进行存储。
初始字符数组大小为16长度超了之后会进行扩容处理。反复扩容也会造成内存和性能的浪费。所以确定的情况下最好设置初始值。 Testpublic void test2() {StringBuffer buffer new StringBuffer();System.out.println(System.identityHashCode(buffer));buffer.append(123);System.out.println(System.identityHashCode(buffer));buffer.append(345);System.out.println(System.identityHashCode(buffer));buffer.append(258);System.out.println(System.identityHashCode(buffer));}//结果
1724731843
1724731843
1724731843
1724731843 声明之后会开辟内存空间通过append方法修改值后对象的内存地址不会发生变化。
append方式被synchronized修饰是线程安全的。
3.StringBuilder
StringBuilder是JDK5.0引入的是对StringBuffer的效率改进。因为虽然StringBuffer线程安全但是效率也较低所以引入了线程不安全但是效率高的StringBuilder。 StringBuilder是可变的字符序列不是线程安全的。底层也是使用字符数组进行存储。
初始字符数组大小为16长度超了之后会进行扩容处理。反复扩容也会造成内存和性能的浪费。所以确定的情况下最好设置初始值。 Testpublic void test3() {StringBuilder builder new StringBuilder();System.out.println(System.identityHashCode(builder));builder.append(123);System.out.println(System.identityHashCode(builder));builder.append(345);System.out.println(System.identityHashCode(builder));builder.append(258);System.out.println(System.identityHashCode(builder));}//结果
540642172
540642172
540642172
540642172
4.线程安全的验证 Testpublic void test4() throws InterruptedException {StringBuilder builder new StringBuilder(20);CountDownLatch latch new CountDownLatch(500000);for (int i 0; i 500000; i) {new Thread(() -{builder.append(1);latch.countDown();}).start();}latch.await();System.out.println(builder.length());CountDownLatch latch1 new CountDownLatch(500000);StringBuffer buffer new StringBuffer();for (int i 0; i 500000; i) {new Thread(() -{buffer.append(1);latch1.countDown();}).start();}latch1.await();System.out.println(buffer.length());}
//结果
499974
500000
多线程同时执行时StringBuffer是线程安全的StringBuilder不是线程安全的