A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 朱志江 中级黑马   /  2013-6-7 21:57  /  2283 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

我所知道的,
StringBuffer是单线程的,效率低,安全用于多线程的程序当中
StringBuilder是多线程的,效率高,不安全,用于单线程中,提高安全性

但是在开发中具体应该用在哪里?这个很让我困惑.希望能帮我解答一下.谢谢各位了.

评分

参与人数 1技术分 +1 收起 理由
刘凯 + 1 赞一个!

查看全部评分

9 个回复

倒序浏览
********************************************我所知道的,
StringBuffer是单线程的,效率低,安全用于多线程的程序当中
StringBuilder是多线程的,效率高,不安全,用于单线程中,提高安全性

但是在开发中具体应该用在哪里?这个很让我困惑.希望能帮我解答一下.谢谢各位了.

********************************************

1. 首先说一下 为什么要用String的容器类:
比如 我们在程序中很容易出现下面的代码
  1. int sum =0;
  2. for(int i=0; i<100; i++){
  3.     sum+= i;
  4. }
复制代码
这里面sum必须一直累加才能保证是求和运算的结果
运算的过程你应该很清楚吧 就是 在栈内存中开辟一个空间  叫sum  一直修改sum中的值

好 现在需求变一下: 我想通过循环产生一个新的字符串“abcdefghi...z”
这个时候  最原始的作法就是仿照上面累加求和的例子做成下面的样子:
  1. String s="";
  2. for(char ch ='a'; ch <='z'; ch++){
  3.   s = s+ch;
  4. }
  5. System.out.println(s);
复制代码
这样会达到目的。但是 注意“abc”这样的事字符串常量对象  常量的意思就是不能被改变  所以字符串常量对象就是一旦被初始化 就不能再改变的
并且这些字符串常量对象全部存储在方法区的常量池里面  这样 你看  
初始化 String s=""的时候 ""存储在常量池里面
第一次循环"a"  第二次循环"ab" 第三次循环“abc” 一直到最后一次循环“abcde...z”产生了这么多常量对象都需要内存空间来存储 全部存储在常量池里面

所以 你想一下 要是你的程序很复杂 设计很多字符串操作  都按照基本数据类型的累加来操作  会浪费很多的内存的空间的  

2. 这样 人们就想:能不能也像对基本数据类型的修改一样,也是在原来的内存空间修改字符串的值而不新开辟内存空间呢?
这样就出现了StringBuffer这个类  这个类的实例 你就可以像String类的实例s一样操作你的想法:
把有s的地方换成
  1. StringBuffer sf= new StringBuffer();
  2. for(char ch ='a'; ch <='z'; ch++){
  3. sf.append(ch+"");
  4. }
  5. System.out.println(sf.toString());
复制代码
这样 每次修改的中间变量都会在堆内存(引用sf指向的内存空间)中进行修改。这样就不会产生很多中间变量存储在常量池了。

3.StringBuilder和StringBuffer
《1》StringBuffer先出现的。是设计成线程同步的。多线程数据访问这个容器时,由于是线程同步,每一个线程都要读这个容器的锁判断是不是被占用。是就要等待。
        这个对锁的判断也是要耗费时间的  即使是没有被占用的情况  线程依旧要判断所得情况
        为了提高线程访问StringBuffer容器的效率  Java工程师们在后面的Java版本中设计出来新的功能和StringBuffer一样的类  只不过没有线程同步这一说
       这样线程访问这个StringBuilder容器的时候,就不用判断锁的使用情况了,极大地提高了效率。
《2》毕老师这个时候说了:那要是也是多线程访问还想用StringBuilder该怎么办? 老师说:自己在StringBuilder所在的代码块加锁即可

评分

参与人数 1技术分 +2 收起 理由
刘凯 + 2 赞一个! 很耐心

查看全部评分

回复 使用道具 举报 1 0
1、StringBuffer是线程安全的可变字符序列,可以安全的用于多个线程,而StringBuilder是非安全的可变字符序列,用于在单线程中使用,因为它的内部没有实现同步。除了这点不同外,基本用法都是相同的;
2、因为字符串缓冲区在单线程中使用比较普遍,所以还是用StringBuilder,它比StringBuffer要快。
3、一般在使用字符串连接,经常需要在字符串后面添加新的字符串的时候用到这两个对象。
比如:String s1 = "abc"+"bc"+"ad";
或者是一个循环不断往后面添加新的字符串时就可以用StringBuilder的append方法往原来的字符串后面添加内容,因为String是不可变的字符序列,用它来连接字符串的时候需要不停的创建新的对象再进行连接,使用StringBuilder或StringBuffer就会高效些。

评分

参与人数 1技术分 +1 收起 理由
刘凯 + 1 赞一个!

查看全部评分

回复 使用道具 举报
张歆明 发表于 2013-6-7 22:48
********************************************我所知道的,
StringBuffer是单线程的,效率低,安全用于多线程 ...

你回复的我都懂,我想问一下,在做项目中哪里能用得到.
回复 使用道具 举报
娄田田 发表于 2013-6-7 22:54
1、StringBuffer是线程安全的可变字符序列,可以安全的用于多个线程,而StringBuilder是非安全的可变字符序 ...

你回复的我都懂,我想问一下,在做项目中哪里能用得到.
回复 使用道具 举报
朱志江 发表于 2013-6-7 23:00
你回复的我都懂,我想问一下,在做项目中哪里能用得到.

你啥时候 要用到字符串累加  你就别用String s=""
改成StringBuilder 或者StringBuffer的形式呗
我之所以从最开始的地方给你写 就是告诉你  你要是在程序或者项目中用到了字符串累加  那就用StringBuilder替代吧 最后用toString()转成字符串
回复 使用道具 举报
朱志江 发表于 2013-6-7 23:00
你回复的我都懂,我想问一下,在做项目中哪里能用得到.

怎么说呢,用到的地方很多,只要你用到String,并且需要重复的去修改字符串中的内容,这时就考虑用StringBuffer和StringBuilder,比如说URL,客户端向服务端请求的URL后面需要连接一些参数,需要加上?name=value&name=value等,这时就可以用到字符串缓冲区往固定的URL后拼接不固定的参数。
回复 使用道具 举报
Heart 中级黑马 2013-6-13 14:00:42
8#
StringBuffer和StringBuilder类都表示内容可以被修改的字符串,StringBuilder是线程不安全的,运行效率高,如果一个字符串变量是在方法里面定义,这种情况只可能有一个线程访问它,不存在不安全的因素了,则用StringBuilder如果要在类里面定义成员变量,并且这个类的实例对象会在多线程环境下使用,那么最好用StringBuffer。
回复 使用道具 举报
可以参见下api,StringBuilder是Jdk1.5后出现的,兼容StringBuffer, 但是不保证同步
项目中用到的地方就是可变的字符串,String是不可变的,所以出现了StringBuffer和StringBuiler
回复 使用道具 举报

楼主你好  如果帖子的问题已经解决,请把帖子的类型改为“已解决”。:)
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马