String 的劣势如何成为 String-builder 的优势。我的意思是我已经知道字符串是不可变的,因为如果假设有五个 String 对象并且如果一个对象发生变化,那么它将反映所有内容并可能导致运行时错误,之后 String-Buffer 是可变的,但至少它是一次同步一个线程。事情进展顺利,最后现在 String-builder 可变,可以访问多个线程。使用起来这么复杂?程序员如何管理它。
2 回答
StringBuffer
是同步的,这意味着它的所有方法都是syncrhonized
,所以它可以在多线程环境中安全地使用,即多个线程可以 StringBuffer
安全地更改和检索实例的内容。
这种能力的代价是当两个线程同时访问StringBuffer
实例时,第二个线程被阻塞,直到第一个线程处理缓冲区。这意味着您的多线程系统在这段时间内变成了单线程。如果这种情况经常发生,您的系统性能可能会比没有锁的情况低得多。
StringBuilder
不同步。这意味着如果 2 个线程同时更改其状态,则结果是不可预测的。因此,您应该自己管理访问策略,方法是同步提供对实例的访问权限的方法,StringBuilder
或者避免多线程访问,例如使用真正不可变的对象(如字符串)或实际上不可变的对象(如每个线程的构建器)。
StringBuffer 仅在您调用一种且仅一种方法时才是线程安全的。 SimpleDateFormat 使用 StringBuffer 但不是线程安全的(它是由 JVM 开发人员编写的)。以线程安全的方式使用 StringBuffer 并做到正确并不容易。
您最好使用十年前取代 StringBuffer 并使用显式synchronized
或Lock
. 对于您的用例,这可能实际上是线程安全的。
如何使用显式同步或锁 -</p>
你在你的操作周围放置一个synchronized
块
例如写一个新行
synchronized(sb) {
sb.append("data: ");
sb.append(data);
sb.append("\n");
}
或抓取内容
String s;
synchronized(sb) {
s = sb.toString(); // no simple way to control how many messages you get
sb.setLength(0);
}
程序员如何管理它。
您很可能想要一种不同的方法。这是因为没有办法轮询 StringBuilder/StringBuffer 并询问它;你完成了吗?如果我读到你,我可以用简单的方式清除它,以便可以重用缓冲区。如果没有可用的数据,没有简单的方法可以阻止。作家也没有并发性。
如果您想在线程之间共享文本流,我建议使用
BlockingQueue<String> textStream = new ConcurrentLinkedQueue<>();
这将是线程安全的,支持并发写入和读取,并且您可以阻止等待一些数据并知道它正是一条消息。