There is an article that I came across while I was looking for a good practice of builder pattern.
In the article, the author mentions about something that drew my attention. the pattern being thread safe.
The first variation of build()
method is thread-safe:
public User build() {
User user = new user(this);
if (user.getAge() > 120) {
throw new IllegalStateException("Age out of range"); // thread-safe
}
return user;
}
Whereas, this one is not:
public User build() {
if (age > 120) {
throw new IllegalStateException("Age out of range"); // bad, not thread-safe
}
// This is the window of opportunity for a second thread to modify the value of age
return new User(this);
}
Although, I think a better approach would be throwing IllegalStateException
in the setters:
public User build() {
User u = null;
try {
u = new User(this);
}
catch(IllegalStateException e){
e.printStackTrace();
}
return u;
}
where the constructor looks like this:
private User(UserBuilder builder)
{
setAge(builder.age);
}
and the setter is:
void setAge(int age) throws IllegalStateException {
if(age > 0 && age < 120) this.age = age;
else throw new IllegalStateException("Age out of range");
}
would my approach still be thread-safe? If not, why? And what is the best way to implement the builder pattern in a thread-safe way?
Aucun commentaire:
Enregistrer un commentaire