Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java StringBuffer还是同步方法?_Java_Multithreading_Stringbuilder_Synchronized_Stringbuffer - Fatal编程技术网

Java StringBuffer还是同步方法?

Java StringBuffer还是同步方法?,java,multithreading,stringbuilder,synchronized,stringbuffer,Java,Multithreading,Stringbuilder,Synchronized,Stringbuffer,我有以下代码: public class MyLogger { private StringBuilder logger = new StringBuilder(); public void log(String message, String user) { logger.append(message); logger.append(user); } } 程序员必须保证一个MyLogger对象对于一个 多线程系统。 必须如何将此代码更改为线程安全的

我有以下代码:

public class MyLogger {
   private StringBuilder logger = new StringBuilder();

   public void log(String message, String user) {
      logger.append(message);
      logger.append(user);
   }
}
程序员必须保证一个MyLogger对象对于一个 多线程系统。 必须如何将此代码更改为线程安全的

A.同步日志方法

B.将
StringBuilder
替换为
StringBuffer


请建议最佳方法。

StringBuffer
不足以保证始终分组发送这两个信息:

  logger.append(message);
  logger.append(user);
它只保证不会以并发方式调用
append()
,这样您就不会冒险破坏
StringBuffer
对象的状态
log()
调用期间,您确实可以有两个线程交错,并获得以下调用:

线程1:logger.append(消息)

线程2:logger.append(消息)

线程1:logger.append(用户)

线程2:logger.append(用户)

这样更好:

  public synchronized void log(String message, String user) {
      logger.append(message);
      logger.append(user);
   }
您还可以在专用
记录器
对象上执行同步。

其优点是不允许类的客户端将其锁定在类之外。

StringBuffer
不足以保证始终分组发送这两个信息:

  logger.append(message);
  logger.append(user);
它只保证不会以并发方式调用
append()
,这样您就不会冒险破坏
StringBuffer
对象的状态
log()
调用期间,您确实可以有两个线程交错,并获得以下调用:

线程1:logger.append(消息)

线程2:logger.append(消息)

线程1:logger.append(用户)

线程2:logger.append(用户)

这样更好:

  public synchronized void log(String message, String user) {
      logger.append(message);
      logger.append(user);
   }
您还可以在专用
记录器
对象上执行同步。

它的优点是不允许类的客户端将其锁定在类之外。

使用,因为如果选择使用StringBuffer,可能会弄乱日志: StringBuffer可能会发生这种情况(将生成错误的日志):

logger.append(消息);<穿过
logger.append(消息);<线程B
logger.append(用户);<穿过
logger.append(用户);<线程B

使用A,因为如果选择使用StringBuffer,可能会弄乱日志: StringBuffer可能会发生这种情况(将生成错误的日志):

logger.append(消息);<穿过
logger.append(消息);<线程B
logger.append(用户);<穿过
logger.append(用户);<线程B

这在logger中累积,重点是什么?我可能不使用其中任何一个,更喜欢保存字符串和命令副本的“LogEntry”类实例,而不是在阻塞队列末尾等待的logger线程。因此,这在logger中累积,重点是什么?我可能不使用任何一个,首选“LogEntry”类实例,该实例保存字符串和命令的副本,并发送给在阻塞队列末尾等待的记录器线程。您可能希望提到,在私有对象上进行同步比在方法签名上使用
synchronized
更好。@Alvin Thompson nice建议。我添加了它。谢谢@davidxxx的精彩描述。如果我的理解有误,请告诉我:比如说,线程1有机会执行logger.append(message);那么T1拥有对SB对象的锁定,并且在方法执行完成后,它将释放对SB的锁定?因此T2可以执行logger.append(消息);这样就可能出现问题?这就是你想要描述的吗?不客气。您很接近了,“在方法执行完成后,它可能会释放锁定”。好的。因此,当T1释放锁并且T2可能开始执行时,即线程1:logger.append(消息);线程2:logger.append(消息);线程1:logger.append(用户);线程2:logger.append(用户);否则,如果T1持有锁,那么它可以继续:logger.append(user);T2将没有机会,所以这将类似于:线程1:logger.append(message);线程1:logger.append(用户);线程2:logger.append(消息);线程2:logger.append(用户);您可能想提到,在私有对象上进行同步比在方法签名上使用
synchronized
更好。@Alvin Thompson建议。我添加了它。谢谢@davidxxx的精彩描述。如果我的理解有误,请告诉我:比如说,线程1有机会执行logger.append(message);那么T1拥有对SB对象的锁定,并且在方法执行完成后,它将释放对SB的锁定?因此T2可以执行logger.append(消息);这样就可能出现问题?这就是你想要描述的吗?不客气。您很接近了,“在方法执行完成后,它可能会释放锁定”。好的。因此,当T1释放锁并且T2可能开始执行时,即线程1:logger.append(消息);线程2:logger.append(消息);线程1:logger.append(用户);线程2:logger.append(用户);否则,如果T1持有锁,那么它可以继续:logger.append(user);T2将没有机会,所以这将类似于:线程1:logger.append(message);线程1:logger.append(用户);线程2:logger.append(消息);线程2:logger.append(用户);