[英]Thread safe Builder Pattern
I want to make my Builder pattern as Thread safe But facing issues in that, below is my code:我想让我的 Builder 模式成为线程安全但面临的问题,下面是我的代码:
// Server Side Code
final class Student {
// final instance fields
private final int id;
private final String name;
private final String address;
public Student(Builder builder)
{
this.id = builder.id;
this.name = builder.name;
this.address = builder.address;
}
// Static class Builder
public static class Builder {
/// instance fields
private int id;
private String name;
private String address;
public static Builder newInstance()
{
return new Builder();
}
private Builder() {}
// Setter methods
public Builder setId(int id)
{
this.id = id;
return this;
}
public Builder setName(String name)
{
this.name = name;
return this;
}
public Builder setAddress(String address)
{
this.address = address;
return this;
}
// build method to deal with outer class
// to return outer instance
public Student build()
{
return new Student(this);
}
}
@Override
public String toString()
{
return "id = " + this.id + ", name = " + this.name +
", address = " + this.address;
}
}
----------
There is another class named StudentReceiver.java in which I am using multithreading:还有另一个名为 StudentReceiver.java 的 class 我正在使用多线程:
class StudentReceiver {
// volatile student instance to ensure visibility
// of shared reference to immutable objects
private volatile Student student;
public StudentReceiver() throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
public void run() {
student = Student.Builder.newInstance().setId(1).setName("Ram").setAddress("Noida").build();
}
});
Thread t2 = new Thread(new Runnable() {
public void run() {
student = Student.Builder.newInstance().setId(2).setName("Shyam").setAddress("Delhi").build();
}
});
t1.start();
t2.start();
//t1.join();
//t2.join();
}
public Student getStudent() {
return student;
}
}
----------
Main class is below from where I am calling these methods:主要的 class 下面是我调用这些方法的地方:
//Driver class
public class BuilderDemo {
public static void main(String args[]) throws InterruptedException
{
for(int i=0; i<10;i++)
{
StudentReceiver sr = new StudentReceiver();
System.out.println(sr.getStudent());
}
}
}
----------
The output I am getting is like below:我得到的 output 如下所示:
null
null
null
null
null
null
null
null
id = 1, name = Ram, address = Noida
null
Why I am getting null here??为什么我在这里得到 null? May anyone explain and How to make Builder Pattern thread safe so that it can be used in multithreaaded environment.
任何人都可以解释以及如何使 Builder Pattern 线程安全,以便它可以在多线程环境中使用。
Your Builder Pattern is not the problem here.您的构建器模式不是这里的问题。 The Constructor of
StudentReceiver
is. StudentReceiver
的构造函数是。
Starting a Thread inside it without joing it there will lead to the object being assigned, possibly and probably before the Thread even started.在其中启动一个线程而不加入它会导致 object 被分配,可能而且可能在线程开始之前。 So the
student
Field will not be set for quite some time.所以在很长一段时间内都不会设置
student
字段。 So much time in fact, that executing the System.out.println(sr.getStudent());
事实上,执行
System.out.println(sr.getStudent());
的时间太多了。 line right after the constructor will (very probably) receive null
from getStundent()
.构造函数之后的行将(很可能)从
getStundent()
接收null
。
The fix would be to either:解决方法是:
And the Builder class should not be static .并且生成器 class 不应该是 static 。
Here is an example of what I'd do:这是我要做的一个例子:
public interface IBuilder
{
IBuilder setId( int id );
// ...
Student build();
}
final class Student {
// final instance fields
private final int id;
// + other fields - left out for brevity
private Student(Builder builder)
{
this.id = builder.id;
// + other fields
}
private static Object builderLock = new Object();
public static IBuilder getBuilder()
{
synchronized(builderLock)
{
return new Builder();
}
}
// Static class Builder
public class Builder implements IBuilder {
// instance fields
private int id = -1;
// ...
private Builder() {}
// Setter methods
public IBuilder setId(int id) {
this.id = id;
return this;
}
public Student build() {
return new Student(this);
}
}
}
Disclaimer: untested!免责声明:未经测试!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.