2009-03-10 31 views
13

Tôi đang xây dựng một Chuỗi ra khỏi nhiều phần và muốn sử dụng hoặc StringBuffer hoặc StringBuilder để làm như vậy. Từ 5 tài liệu Java, tôi thấy rằng StringBuilder được ưa thích khi có thể, với sự báo trước rằngJava StringBuilder và An toàn Chủ đề

Instances của StringBuilder không an toàn để sử dụng bởi nhiều chủ đề.

Từ tuyên bố này, tôi hiểu rằng tôi không nên có một cá thể StringBuilder được chia sẻ bởi nhiều chủ đề. Nhưng những gì về trường hợp này:

//Is this safe? 
//foo() is called simultaneously by multiple threads 
String foo(String a, String b) { 
    return new StringBuilder(a).append(b).toString(); 
} 

Ở đây có thể có nhiều chủ đề trong chức năng cùng một lúc, sử dụng lớp StringBuilder cùng một lúc (ví dụ, truy cập đồng thời các biến tĩnh, nếu có bất kỳ), nhưng mỗi chuỗi sẽ có một phiên bản riêng biệt là StringBuilder. Từ tài liệu, tôi có thể không hoàn toàn quyết định xem điều này được tính là sử dụng bởi nhiều chủ đề hay không.

+0

có thể có một số lợi ích khi thực hiện foo() một phương thức tĩnh, vì nó không chạm vào bất kỳ biến mẫu nào. – Kip

+0

@Kip: Tùy thuộc vào lớp học. Nhưng một số lần bạn có thể muốn thực hiện các hoạt động đa hình và làm cho phương thức tĩnh sẽ cản trở điều này. – OscarRyz

+0

Sử dụng String.concat sẽ nhanh hơn, nhưng tôi nghĩ đây chỉ là một ví dụ. –

Trả lời

19

Điều đó hoàn toàn ổn. Các biến cục bộ không có vấn đề gì với an toàn luồng miễn là chúng không truy cập hoặc biến đổi các biến của lớp hoặc biến thể.

11

Có, đó là an toàn, bởi vì đối tượng StringBuilder chỉ được sử dụng cục bộ (mỗi thread gọi foo() sẽ tạo ra StringBuilder của riêng nó).

Bạn cũng nên lưu ý rằng mã bạn được đăng là thực tế giống với bytecode tạo của thành viên này:

String foo(String a, String b) { 
    return a + b; 
} 
+0

Làm thế nào để bạn thấy rằng bytecode? – OscarRyz

+0

@Oscar: javap -c

+0

cũng xem: http://stackoverflow.com/questions/272535/how-do-i-decompile-java-class-files – Kip

4

Đồng ý với câu trả lời khác - chỉ cần một lưu ý.

Nếu có trường hợp StringBuffer đang được sử dụng bởi nhiều luồng, nó có thể là một trường hợp sử dụng hoàn toàn bị hỏng bởi vì nó có nghĩa là một chuỗi được xây dựng theo thứ tự gần như ngẫu nhiên, để làm cho chuỗi StringBuffer an toàn.

+0

Đó là lý do của StringBuilder. Hầu hết các lần đồng bộ hóa là không cần thiết. – OscarRyz

+0

Có, điều này khiến bạn tự hỏi tại sao họ không chỉ viết lại StringBuffer thay vì tạo StringBuilder song song. Để giữ tính tương thích ngược cho ứng dụng xây dựng chuỗi không xác định? –

+1

Có thể nếu bạn đang sử dụng một StringBuilder cho một số loại ghi nhớ trong bộ nhớ của một ứng dụng đa luồng? Không chắc chắn lý do tại sao bạn sẽ làm điều đó mặc dù ... – Kip

3

Tôi không chắc chắn nếu mã này là cần thiết, bởi vì Java chọn StringBuilder tự động tôi đoán. Nếu bạn không gặp sự cố về hiệu suất, hãy đi tới dấu + b.

Trong trường hợp cần thực hiện, hãy thử rằng:

return new StringBuilder(
a.length() + b.length()).append(a).append(b).toString(); 

Nó kích thước một cách chính xác các bộ đệm và ngăn ngừa VM từ thay đổi kích thước nó và tạo ra rác để thu thập trên đường đi.

6

Mã bạn có là an toàn.

Mã này không.

public class Foo 
{ 
    // safe 
    private final static StringBuilder builder; 

    public static void foo() 
    { 
     // safe 
     builder = new StringBuilder(); 
    } 

    public static void foo(final String a) 
    { 
     // unsafe 
     builder.append(a); 
    } 

    public synchronized void bar(final String a) 
    { 
     // safe 
     builder.append(a); 
    } 
} 

Biến cục bộ chỉ sử dụng dữ liệu cục bộ không có vấn đề an toàn chủ đề. Bạn chỉ có thể có các vấn đề an toàn khi bạn bắt đầu xử lý dữ liệu có thể nhìn thấy ở lớp hoặc phương thức thể hiện/mức biến.