首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >线程安全生成器模式

线程安全生成器模式
EN

Stack Overflow用户
提问于 2020-07-02 07:38:16
回答 1查看 209关注 0票数 0

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

代码语言:javascript
复制
// 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的类,在其中我使用多线程:

代码语言:javascript
复制
    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;
    }
}


----------

主类位于我调用这些方法的位置下面:

代码语言:javascript
复制
//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());
     }
 } 
}


----------

我得到的输出如下:

代码语言:javascript
复制
null
null
null
null
null
null
null
null
id = 1, name = Ram, address = Noida
null

我为什么要在这里变零??请任何人解释,以及如何使Builder模式线程安全,以便在多重环境中使用。

EN

回答 1

Stack Overflow用户

发布于 2020-07-02 08:25:20

您的Builder模式不是这里的问题。StudentReceiver的构造器是。

在它内部启动一个线程而不加入它就会导致对象被分配,甚至可能甚至在线程启动之前。因此,student字段将在相当长的时间内不会被设置。事实上,在构造函数之后执行System.out.println(sr.getStudent());行(很可能)会收到来自getStundent()null

解决办法是:

Constructor.

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

而且Builder类不应该是静态的。

下面是我要做的事情的一个例子:

代码语言:javascript
复制
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);
        }
    }
}

免责声明:未经测试!

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62691317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档