线程安全生成器模式



我想让我的生成器模式成为线程安全 但是面对这方面的问题,下面是我的代码:

// 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; 
} 
} 


----------

还有一个名为 StudentReceiver 的类.java我在其中使用多线程:

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;
}
}

----------

主类在下面,我从下面调用这些方法:

//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());
}
} 
}

----------

我得到的输出如下所示:

null
null
null
null
null
null
null
null
id = 1, name = Ram, address = Noida
null

为什么我在这里得到空?? 任何人都可以解释和如何使生成器模式线程安全,以便它可以在多环境中使用。

您的构建器模式不是这里的问题。StudentReceiver的构造函数是。

在其中启动一个线程而不在那里开玩笑将导致对象被分配,可能并且可能在线程开始之前。因此,student字段在相当长的一段时间内不会设置。事实上,时间如此之长,以至于在构造函数之后立即执行System.out.println(sr.getStudent());行将(很可能(从getStundent()接收null

解决方法是:

  • 不要在构造函数中使用单独的线程。
  • 或者将线程加入构造函数中的线程(这在某种程度上违背了线程的目的(。

并且生成器类不应该是静态的

以下是我要做的一个例子:

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);
}
}
}

免责声明:未经测试!

最新更新