私たちが知っている、文字列は、文字列が参照する読み取り専用の文字列、定義されたら、それは変更することはできませんです。
スプライシングまたはインターセプトアクションの文字列は、文字列の大規模な数を変更する必要がある場合、文字列が非常に低いパフォーマンスを使用して、新しいStringオブジェクトを作成します。
例に続いて、スプライシング100,000文字列、約500倍よりも遅い文字列のStringBuilderのパフォーマンス。
public static void main(String[] args) {
String s = "";
long t1 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
s += "0";
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
//耗时:5106ms
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
sb.append("0");
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
//耗时:9ms
}
このように、文字列が頻繁に変更が必要な場合、あなたは文字列を使用していない、あなたは、StringBuilderのか、StringBufferのを使用する必要があります。
StringBuilderとStringBufferの違い
スレッドセーフ
最大の違いは次のとおりです。スレッドセーフです。
StringBufferのは、スレッドセーフですが、StringBuilderのは、スレッドセーフではありません。
マルチスレッドのStringBuilderに不測の異常やエラーをもたらす、というこれが意味。
それは、後に危険なのStringBuilderを詳細に説明します。
演奏
StringBufferのパフォーマンスが相対的に低いことをスレッドセーフ、スレッドセーフな手段です。
外部被ばくStringBufferのメソッドが追加されているsynchronized
JDKのロック機構は重く、最適化されているが、それぞれが競合してリリースロックに文字列のニーズを修正することを意味するキーワードを、が、それはまだ余分なパフォーマンスを消費する必要があります。
以下の例は、文字列千万スプライシング、StringBuilderをするStringBufferの3倍のパフォーマンス。
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
sb.append("0");
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
//耗时:121ms
}
public static void main(String[] args) {
StringBuffer sb = new StringBuffer();
long t1 = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++) {
sb.append("0");
}
long t2 = System.currentTimeMillis();
System.out.println(t2 - t1);
//耗时:361ms
}
あなたは、スレッドの安全性を考慮していない場合はこのように、パフォーマンスを向上させるためのStringBuilderを使用することを検討してください。
キャッシュ
StringBufferのサポート・キャッシングが、StringBuilderのはサポートされていません。
StringBufferののtoStringが、結果はキャッシュプロパティに文字の配列になりますときにtoStringCache
限り、コンテンツが文字列を変更しないように、後続の各のtoStringは直接取るtoStringCache
文字の配列をコピーせずに、Stirngを構築します。
StringBuilderのキャッシュなし、毎回文字列を構築するための新しいコピー必見のtoString文字配列。
StringBufferの文字列限り内容が変更されているように、toStringCacheはnullに設定されます。
StringBufferのtoString()メソッド
@Override
public synchronized String toString() {
if (toStringCache == null) {
toStringCache = Arrays.copyOfRange(value, 0, count);
}
return new String(toStringCache, true);
}
StringBuilderのtoString()メソッド
@Override
public String toString() {
// Create a copy, don't share the array
return new String(value, 0, count);
}
安全でないのStringBuilder
私はすでにのStringBuilderが表示され、複数のスレッドを使用することで、スレッドセーフな、珍しいと予測不可能なエラーではない、と述べています。
だから、最後には珍しい何も起こりませんか?
期待される結果は矛盾しています
マルチスレッドのStringBuilderを操作するには、文字列の最終結果は予想と矛盾している可能性があります。
次の例で、文字列が期待される内容と矛盾しています。
public static void main(String[] args) throws InterruptedException {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
//Sleep后,结果更明显
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
sb.append("1");
}).start();
}
Thread.sleep(1000);
System.out.println("预期结果:1111111111");
System.out.println("实际结果:"+sb.toString());
}
次のようにコンソール出力は次のようになります。
预期结果:1111111111
实际结果:111111
ArrayIndexOutOfBoundsExceptionが
マルチスレッドのStringBuilderはappend()メソッドは、中の内部配列のコピーを投げることができる呼び出しArrayIndexOutOfBoundsException
異常。
例としては、次のとおりです:
public static void main(String[] args) throws InterruptedException {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
new Thread(()->{
try {
//Sleep后,结果更明显
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//append字符串长度越长越容易抛异常
sb.append("000000000000000000000000000000000000000000000000000");
}).start();
}
}
コンソール例外:
追記()メソッドの構文解析
StringBuilderのはappend()が直接、親クラスの呼び出しをAbstractStringBuilder
使用すると、親クラスに直接スキップすることができますので、この方法を。
appendメソッドは、複数のスレッドが同時に呼び出すことを意味し、ロックされていません。
それは同時呼び出しているので、それが元スレッドにつながる実行されていないcount += len
スレッドの背面のコードは、エラーをスレッドの拡大で、その結果、文字の配列の拡張操作していて、正しいサイズへの拡大は、その結果、存在しないstr.getChars()
スローされた操作ArrayIndexOutOfBoundsException
例外。
もちろん、必ずしもすべての時間が例外をスローします。
StringBuilderの文字列の既定のサイズは16で、拡張ロジックがあるためである当前大小*2+2
アペンド文字の長さでも、エラー文字列の拡張場合、短い場合、容量が十分に良いです、それは異常を投げることはありません。
ただし、例外をスローしない場合は、マルチスレッドカウントのプロパティのためには、混乱の下にあるアペンド文字が文字列の期待と矛盾する結果として、上書きされる前に、ある文字の配列、の障害のあるコピーにつながります。
それはマルチスレッド環境であれば、それは外部の追加の方法を暴露するのでそう、、StringBufferのを使用することを忘れないでくださいsynchronized
キーワードを、あなたは、同時にセキュリティを確保することができます。