我听说 Date
不是线程安全的问题,但还没有找到任何实际的解释,这可能会导致糟糕的结果。我知道用 DateFormat
解析时会很糟糕,但是 Date
?
作为一个例子,使用下面的 Date 会导致多线程环境变得很糟糕吗?
@Transactional(rollbackFor = {Throwable.class})
public void moveToArchive(UserContext userContext, long id) throws PostFailedException {
PostEntity postEntity;
try {
postEntity = postDAO.get(userContext.getUserId(), id);
} catch (EntityNotFoundException ex) {
throw new PostFailedException(PostFailedException.ITEM_NOT_FOUND, ex);
}
//...
// copying java.util.Date between entities
archivedPostEntity.setCreationDate(post.getCreationDate());
//...
}
那么如果 getCreationDate
仅返回内部属性会很糟糕吗?或者 Spring/Hibernate 会正确处理这个问题吗?
getCreationDate
应该是什么样子?
这样的事情可以吗?
@Entity
public class PostEntity implements Post {
//...
@NotNull
@Temporal(value = TemporalType.TIMESTAMP)
private Date postDate;
//...
@Override
public Date getPostDate() {
return postDate;
}
}
或者也许应该更像这样?
@Entity
public class PostEntity implements Post {
//...
@NotNull
@Temporal(value = TemporalType.TIMESTAMP)
private Date postDate;
//...
@Override
public synchronized Date getPostDate() {
return new Date(postDate.getTime());
}
}
最佳答案
Java Date 对象不是线程安全的。您通过 getPostDate() 方法创建新日期的方法将在很大程度上避免此问题。事实上,这被认为是最佳实践。
现在,无论线程安全如何,建议您在从实体返回时重新创建(克隆或其他方式)Date 对象。 FindBugs 实际上会在您的 POJO 中查找此问题。原因是 Date 是可变的,与 String 类不同。
因此,从实体 bean 返回实时引用允许更改实体中的 Date 对象,而无需在实体中使用相应的 set 方法。该实体将不知道其内部状态是否已更改以及是否需要将其保留到数据存储中。这种缺陷发生的频率比您愿意承认的要高。
希望这能回答您的问题。
关于java - 是否应该在进入 Java 之前克隆 Date 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47796565/