Шаблон проектирования Builder, возвращает нуль в многопоточной среде - PullRequest
1 голос
/ 23 октября 2019

Я читал о шаблоне здесь:

https://www.geeksforgeeks.org/builder-pattern-in-java/

последняя часть демонстрирует, как использовать шаблон, я попытался скопировать код в мою IDE и запустить его, но онвозвращает ноль,

код:

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

// Client Side Code 
class StudentReceiver {

    // volatile student instance to ensure visibility
    // of shared reference to immutable objects
    private volatile Student student;

    public StudentReceiver() {

        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                student = Student.Builder.newInstance().setId(1).setName("Ram").setAddress("Noida").build();
                System.out.println(student.toString());
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                student = Student.Builder.newInstance().setId(2).setName("Shyam").setAddress("Delhi").build();
                System.out.println(student.toString());
            }
        });

        t1.start();
        t2.start();
    }

    public Student getStudent() {
        return student;
    }
}

// Driver class 
public class BuilderDemo {
    public static void main(String args[]) {
        StudentReceiver sr = new StudentReceiver();
        System.out.println("sr " + sr.getStudent());
    }
}

Когда я удаляю потоки и запускаю их без них, это работает, у любого есть представление о том, почему он возвращает ноль вместо одного из объектов студента?

1 Ответ

2 голосов
/ 23 октября 2019

В вашем коде основной поток выполняется до того, как получатель студента выполнит код.

Thread t1 = new Thread(new Runnable() {
    @Override
    public void run() {
        student = Student.Builder.newInstance().setId(1).setName("Ram").setAddress("Noida").build();
        System.out.println(student.toString());
    }
});

t1.start(); // It starts, but the runnable itself has not run yet!

Итак, сначала вы получаете студента, который равен null, и распечатываете его в main, затем инициализируется StudentReceiverваш ученик.

Посоветуйте, не делайте этого в реальных задачах, но делайте это для обучения!

Кроме того, вы можете подождать, пока пользователь не инициализируется. Это один подход.

try {
    t1.join();
    t2.join();
} catch (Exception e) {
    throw new RuntimeException("Handle it properly.", e);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...