![](/img/trans.png)
[英]When a method is synchronized, can we use StringBuilder over StringBuffer?
[英]Why Java uses StringBuffer (synchronized) when StringBuilder is faster?
我正在查看Java反射類,並注意到了這段代碼。 我想知道,當StringBuilder更快時,為什么Java使用StringBuffer?
Java不想使用最快的實現,還是有其他原因?
該代碼在Field.class中:
static String getTypeName(Class<?> type) {
if (type.isArray()) {
try {
Class<?> cl = type;
int dimensions = 0;
while (cl.isArray()) {
dimensions++;
cl = cl.getComponentType();
}
StringBuffer sb = new StringBuffer();
sb.append(cl.getName());
for (int i = 0; i < dimensions; i++) {
sb.append("[]");
}
return sb.toString();
} catch (Throwable e) { /*FALLTHRU*/ }
}
return type.getName();
}
主要原因是JVM具有先進的技術,可以查看是否可以避免執行上下文暗示的所有事情。 由於StringBuffer是一個永遠不會逸出該方法的局部變量,因此JVM可以安全地避免在進入StringBuffer的同步方法之前必須嘗試獲取該對象的鎖-因為沒有其他線程能夠調用該特定方法StringBuffer的實例。
快速的微基准測試證明了這一點。 將buffer
一個字段會使以下代碼減慢50%。
private void doTest(String toCopy) {
StringBuffer buffer = new StringBuffer();
for (int i = 0; i < toCopy.length(); i++) {
buffer.append(toCopy.charAt(i));
}
buffer.toString();
}
使用一百萬個長度的字符串和1000次重復,以上代碼在我的機器上運行8秒鍾。 但是,一旦將buffer
為字段而不是局部變量,則將花費約13秒的時間(因為JVM不再能夠輕松保證buffer
只能由一個線程訪問)。
如果對我有用的話,首先會介紹Stringbuffer,所以這可能是一段較舊的代碼。 真正的原因必須是線程安全,盡管在緩沖區是stringbuilder時不是安全的。
我見過面並問了幾個JVM開發人員,為什么仍然使用StringBuffer如此之多,因為他們建議人們在8年前取代替代品而遷移到StringBuilder。 我覺得這不是他們擔心/想到的事情。 產品經理之一沒有任何正式理由。
我認為為什么Java編碼約定(1999)建議您使用空格時JDK源代碼使用制表符。 使用代碼格式化程序可輕松解決此問題,但在任何人的待辦事項列表中都不會發現。
恕我直言,StringBuffer從來就不是使多線程成為一個好主意的主意。 在極少數情況下,您可能想以多線程方式寫入內存中的字符流,而不必擔心產生的文本有多混亂,您仍然可以使用更自然的替代方法,例如StringWriter( (在Java 1.0中可用)或同步StringBuilder。
我相信它實際上解決了許多錯誤,例如SimpleDateFormat使用了它,並且即使它不是線程安全的,在某種程度上仍然使用StringBuffer。 可能使用線程安全集合給某些開發人員一種錯誤的安全感,或者看起來有些線程安全。 即在多個線程中使用StringBuffer而不是StringBuilder更可能通過簡單的測試,即使認為可能存在錯誤。
例如考慮兩個線程編寫
sb.append("Hello ").append("World").append("\n");
問題在於,雖然每個append
同步,但每個代碼塊都不同步。 所以你可以得到
Hello Hello World World\n\n
要么
Hello World Hello \nWorld\n
因此,如果只使用一次append,StringBuffer僅是線程安全的,無需同步,這使其毫無意義。
我嘗試指出當涉及StringBuffer的問題發布在SO上時要切換的人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.