Implementing a thread-safe factory with caching
If you are on Java 8, you can use a cool new feature of ConcurrentMap: computeIfAbsent.

It lets you defer the actual construction of the Connection until it becomes necessary and makes your code more concise:

private static ConcurrentMap&lt;ConnectionSettings, Connector&gt; connectorCache =
    new ConcurrentHashMap&lt;ConnectionSettings, Connector&gt;();

public static Connector newConnection(String url, String user, String psswd)
        throws ConfigurationException {

    ConnectionSettings settings = new ConnectionSettings(url, user, psswd);
    return connectorCache.computeIfAbsent(settings, Connector::new);
}


Note the two arguments to computeIfAbsent:


The first is your ConnectionSettings instance, which is used as a key.
The second is an instance of the interface Function. If called, it gets the settings as an argument and must return an instance of Connector. The function is defined by using a lambda expression, in this case a constructor reference. This is possible because the constructor of Connector does exactly that: it takes the settings as an argument and returns a Connector instance.


The call tells your connectorCache to check for the specified settings. If they exist the corresponding connector is returned. If not (and only then!) is the function executed, which creates a new Connector. (Of course in that case the new instance is put into the map.)

So you see the constructor is only invoked if needed. All necessary locking for concurrency is done by the map and you don't have to worry about it.