Life

Thursday, June 28, 2018

String-StringBuffer-StringBuilder

String、StringBuffer、StringBuilder之间有什么区别呢?
先说一说String和StringBuffer的不同之处。
String 类型和 StringBuffer 类型的主要性能区别其实在于 String 是不可变的对象,因此在每次对 String 类型进行改变的时候其实都等同于生成了一个新的 String 对象,然后将指针指向新的 String 对象,所以经常改变内容的字符串最好不要用 String ,因为每次生成对象都会对系统性能产生影响。
而如果是使用 StringBuffer 类则结果就不一样了,每次结果都会对 StringBuffer 对象本身进行操作,而不是生成新的对象,再改变对象引用。
所以在一般情况下推荐使用 StringBuffer ,特别是字符串对象经常改变的情况下。而在某些特别情况下,String 对象的字符串拼接其实是被 JVM 解释成了 StringBuffer 对象的拼接,所以这些时候 String 对象的速度并不会比StringBuffer 对象慢,而特别是以下的字符串对象生成中, String 效率是远要比 StringBuffer 快的。
String S1 = “This is only a” + “ simple” + “ test”;
StringBuffer Sb = new StringBuilder(“This is only a”).append(“ simple”).append(“ test”);
你会惊讶的发现,生成 String S1 对象的速度简直太快了,
而这个时候 StringBuffer 居然速度上根本一点都不占优势。其实这是 JVM对String类进行的优化处理,在JVM眼里,这句生成 String S1 对象的代码相当于

String S1 = “This is only a simple test”;
       StringBuffer是Synchronized的,即线程安全的。如果要频繁对字符串内容进行修改,出于效率考虑最好使用 StringBuffer,如果想转成 String 类型,可以调用 StringBuffer 的 toString() 方法。
      StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。
      append 方法始终将这些字符添加到缓冲区的末端; insert 方法则在指定的点添加字符。 例如,如果 z 引用一个当前内容是 start 的字符串缓冲区对象,则此方法调用 z.append(“le”) 会使字符串缓冲区包含 startle ,而 z.insert(4, “le”) 将更改字符串缓冲区,使之包含 starlet 。
      再看StringBuilder。java.lang.StringBuilder是一个可变的字符序列,是5.0新增的。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。
      因此,在大部分情况下,StringBuilder > StringBuffer。这主要是由于前者不需要考虑线程安全。
总结一下:
  1. 1>如果要操作少量的数据,用String ;单线程操作大量数据,用StringBuilder ;多线程操作大量数据,用StringBuffer。
  2. 2>不要使用String类的”+”来进行频繁的拼接,因为那样的性能极差的,应该使用StringBuffer或StringBuilder类,这在Java的优化上是一条比较重要的原则。
  3. 3>为了获得更好的性能,在构造 StringBuffer 或 StringBuilder 时应尽可能指定它们的容量。当然,如果你操作的字符串长度(length)不超过 16 个字符就不用了,当不指定容量(capacity)时默认构造一个容量为16的对象。不指定容量会显著降低性能。
  4. 4>StringBuilder 一般使用在方法内部来完成类似 + 功能,因为是线程不安全的,所以用完以后可以丢弃。StringBuffer 主要用在全局变量中。
  5. 5>相同情况下使用 StringBuilder 相比使用 StringBuffer 仅能获得 10%~15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因此:除非确定系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,才可以采用 StringBuilder;否则还是用 StringBuffer。
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2018/12/string-stringbuffer-stringbuilder.html

Monday, June 11, 2018

sleep()与wait()的区别

1.

这两个方法来自不同的类.分别是:sleep来自Thread类,和wait来自Object类。

2.

最主要是sleep方法没有释放锁,而wait方法释放了锁,使得其他线程可以使用同步控制块或者方法。
sleep不出让系统资源,sleep方法只让出了CPU,而并不会释放同步资源锁,sleep() 是static静态的方法,他不能改变对象的机锁,当一个synchronized块中调用了sleep() 方法,
线程虽然进入休眠,但是对象的机锁没有被释放,其他线程依然无法访问这个对象;
wait是进入线程等待池等待,出让系统资源,其他线程可以占用CPU。一般wait不会加时间限制,因为如果wait线程的运行资源不够,
再出来也没用,要等待其他线程调用notify/notifyAll唤醒等待池中的所有线程,
才会进入就绪队列等待OS分配系统资源。sleep(milliseconds)可以用时间指定使它自动唤醒过来,
如果时间不到只能调用interrupt()强行打断。

3.

使用范围:wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,
而sleep可以在任何地方使用
synchronized(x){
x.notify()
//或者wait()
}

4.

sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常
版权声明
本博客所有的原创文章,作者皆保留版权。转载必须包含本声明,保持本文完整,并以超链接形式注明作者Leslie Tien和本文原始地址:
https://leslietien.blogspot.com/2018/12/sleepwait.html