...
Method chaining is a useful design pattern for building an object and setting its optional fields. A class that supports method chaining provides several setter methods that each return the this
reference. However, in a multithreaded environment, a thread may observe shared fields to contain inconsistent values. This noncompliant code example shows the Javabeans JavaBeans pattern which is not safe for multithreaded use.
Code Block | ||
---|---|---|
| ||
final class USCurrency { // Change requested, denomination (optional fields) private int quarters = 0; private int dimes = 0; private int nickels = 0; private int pennies = 0; public USCurrency() {} // Setter methods public USCurrency setQuarters(int quantity) { quarters = quantity; return this; } public USCurrency setDimes(int quantity) { dimes = quantity; return this; } public USCurrency setNickels(int quantity) { nickels = quantity; return this; } public USCurrency setPennies(int quantity) { pennies = quantity; return this; } } // Client code: private final USCurrency currency = new USCurrency(); // ... new Thread(new Runnable() { @Override public void run() { currency.setQuarters(1).setDimes(1); } }).start(); new Thread(new Runnable() { @Override public void run() { currency.setQuarters(2).setDimes(2); } }).start(); |
The Javabeans JavaBeans pattern uses a no-argument constructor and a series of parallel setter methods to build an object. This pattern is not thread-safe and can lead to inconsistent object state. In this example, a client that constructs a USCurrency
object and starts two threads as shown may find the object to contain two quarters and one dime or one quarter and two dimes, contrary to what it expects.
...