我想让我的生成器模式成为线程安全 但是面对这方面的问题,下面是我的代码:
// 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);
}
}
}
免责声明:未经测试!