Reputation: 1617
I was reading about the pattern here:
https://www.geeksforgeeks.org/builder-pattern-in-java/
the last part demonstrates how to use the pattern, I tried to copy the code into my IDE & run it but it returns null,
the 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;
}
}
// 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());
}
}
When I remove the threads and run it without them it works, anyone has an idea of why it returns null instead of one of the student objects ?
Upvotes: 1
Views: 594
Reputation: 13103
In your code, main thread is executed before student receiver executes the code.
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!
So first you get the student which is null
and print it in main, then StudentReceiver
will initialize your student.
Advise, do not do it in real world tasks, but do it for learning!
Alternatively, you can wait until the user is initialized. This is one approach.
try {
t1.join();
t2.join();
} catch (Exception e) {
throw new RuntimeException("Handle it properly.", e);
}
Upvotes: 2