This is the first time I am writing a Factory
class. Below is my Factory class, I am not sure whether this is the correct way of making thread safe Singleton Factory class or not. I will be returning instance of my Client using this factory?
public class ClientFactory {
private static ClientFactory instance = null;
private ClientFactory() {
}
public static ClientFactory getInstance() {
if (instance == null)
{
instance = new ClientFactory();
}
return instance;
}
public IClient getClient() {
return new TestClient();
}
}
And here is my TestClient class -
public class TestClient implements IClient {
}
And this is how I am going to use my factory -
IClient client = ClientFactory.getInstance().getClient();
In fact your factory isn't thread safe, because in race condition you can have more than one ClientFactory living in application. Lets assume two threads:
- ThreadA is evaluating condition 'if (instance == null)' and instance is null, so it enters statement
- ThreadB is evaluating condition 'if (instance == null)' and instance is null (because A didn't make to instantiate it), so it enters statement
- ThreadA creates new ClientFactory() and returns it
- ThreadB creates new ClientFactory() and returns it
- Now we have more than one ClientFactory in application. Of course other threads trying to retrieve instance some time later will always return single instance.
In my opinion the easiest way to write singleton in Java is to use enum. In your case it will looks:
public enum ClientFactory {
INSTANCE;
public Company getClient() {
return new Company();
}
}
And usage:
ClientFactory.INSTANCE.getClient()
Thread safe implementations(examples) on Wiki - Singleton Pattern on Wikipedia
As in the link above, a single-element enum
type is the best way to implement a Singleton for any Java that supports enums.
One of the best yet simple ones:
public class ClientFactory{
private ClientFactory() {}
private static ClientFactory INSTANCE=null;
public static ClientFactory getInstance() {
if(INSTANCE==null){
synchronize(ClientFactory.class){
if(INSTANCE==null) // check again within synchronized block to guard for race condition
INSTANCE=new ClientFactory();
}
}
return INSTANCE;
}
}
Source:
Wikipedia
Singletons and Factories are different things. To property construct a Singleton, I guess you could think of its getInstance() method as a factory. Factories make "things". Singleton means that there will only ever be 0 or exactly 1 of these "things" in existence at any time.
If you are trying to make a proper Singleton, it is surprisingly cumbersome to do this in a Thread-safe manner in Java. Without synchronization or other thread-safe countermeasures, the code you list above has a subtle race-condition around the check-then-set code to initialize ClientFactory instance variable. There are two ways around this race-condition. Which way you pick is largely gated by how expensive it is to go through the ClientFactory constructor. My constructors are typically lightweight, so I go the path of avoiding the need for synchronization all together.
public class ClientFactory {
private static final ClientFactory instance = new ClientFactory();
private ClientFactory() { }
public static ClientFactory getInstance() {
return instance;
}
}
If you want to be "lazy" in the construction, not building on until someone explicitly calls getInstance(), now synchronization is needed to avoid the race condition.
public class ClientFactory {
private static ClientFactory instance = null;
private ClientFactory() { }
public static synchronized ClientFactory getInstance() {
if ( instance == null ) {
instance = new ClientFactory();
}
return instance;
}
}
Your factory is a perfect Singleton (it is just that it is not thread-safe).
the ClientFactory is a factory,but neither a Singleton Factory,nor a thread-safe factory. At any point,when ClientFactory.getInstance().getClinet() is invoked,it will return a new instance,so it is not absolutely a Singleton Factory.If we fix the method like this
private IClient iclient;
public IClient getClient() {
if ( iclient == null ){
iclient = new TestClient();
}
return iclient ;
}
Then the factory is a singleton factory,but it is not thread-safe. Assume if there are more than one threads invoke getInstance,all of the threads will find that the client factory instance is null,so they will construct the instance respectively, and the problem is the same with the method getClient().
It is very easy to fix it,you can declare these two method as synchronized.
First of all,if you really want to use factory parrtern,don't forget to hidden the client's Constructor
private TestClient(){
}
来源:https://stackoverflow.com/questions/21033112/how-to-correctly-make-a-thread-safe-singleton-factory-in-java