Thread-Safe classe singleton
J'ai écrit ci-dessous classe Singleton. Je ne suis pas sûr de savoir si c'est thread-safe classe singleton ou pas?
public class CassandraAstyanaxConnection {
private static CassandraAstyanaxConnection _instance;
private AstyanaxContext<Keyspace> context;
private Keyspace keyspace;
private ColumnFamily<String, String> emp_cf;
public static synchronized CassandraAstyanaxConnection getInstance() {
if (_instance == null) {
_instance = new CassandraAstyanaxConnection();
}
return _instance;
}
/**
* Creating Cassandra connection using Astyanax client
*
*/
private CassandraAstyanaxConnection() {
context = new AstyanaxContext.Builder()
.forCluster(ModelConstants.CLUSTER)
.forKeyspace(ModelConstants.KEYSPACE)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2"))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getEntity();
emp_cf = ColumnFamily.newColumnFamily(
ModelConstants.COLUMN_FAMILY,
StringSerializer.get(),
StringSerializer.get());
}
/**
* returns the keyspace
*
* @return
*/
public Keyspace getKeyspace() {
return keyspace;
}
public ColumnFamily<String, String> getEmp_cf() {
return emp_cf;
}
}
Quelqu'un peut-il m'aider? Toute réflexion sur mon ci-dessus classe Singleton sera d'une grande aide.
Code Mis À Jour:-
Je suis en train d'intégrer Bohème suggestion dans mon code. Voici le code mis à jour, j'ai obtenu-
public class CassandraAstyanaxConnection {
private static class ConnectionHolder {
static final CassandraAstyanaxConnection connection = new CassandraAstyanaxConnection();
}
public static CassandraAstyanaxConnection getInstance() {
return ConnectionHolder.connection;
}
/**
* Creating Cassandra connection using Astyanax client
*
*/
private CassandraAstyanaxConnection() {
context = new AstyanaxContext.Builder()
.forCluster(ModelConstants.CLUSTER)
.forKeyspace(ModelConstants.KEYSPACE)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setDiscoveryType(NodeDiscoveryType.RING_DESCRIBE)
)
.withConnectionPoolConfiguration(new ConnectionPoolConfigurationImpl("MyConnectionPool")
.setPort(9160)
.setMaxConnsPerHost(1)
.setSeeds("127.0.0.1:9160")
)
.withAstyanaxConfiguration(new AstyanaxConfigurationImpl()
.setCqlVersion("3.0.0")
.setTargetCassandraVersion("1.2"))
.withConnectionPoolMonitor(new CountingConnectionPoolMonitor())
.buildKeyspace(ThriftFamilyFactory.getInstance());
context.start();
keyspace = context.getEntity();
emp_cf = ColumnFamily.newColumnFamily(
ModelConstants.COLUMN_FAMILY,
StringSerializer.get(),
StringSerializer.get());
}
/**
* returns the keyspace
*
* @return
*/
public Keyspace getKeyspace() {
return keyspace;
}
public ColumnFamily<String, String> getEmp_cf() {
return emp_cf;
}
}
Quelqu'un peut jeter un oeil et laissez-moi savoir si cette fois je l'ai eu raison ou pas?
Merci pour l'aide.
- Oui il c'thread-safe, aussi longtemps que le
Keyspace
etColumnFamily
classe sont trop. Il n'est pas optimale, cependant, vous allez obtenir beaucoup de contention sur la classe de synchronisation dans getInstance(). Vous devez rechercher la "enum pattern singleton". - voir javarevisited.blogspot.dans/2012/07/... et stackoverflow.com/questions/427902/... et peut-être répondre à votre propre question avec de nouveaux enum version de votre classe ty @eurobur pour le signaler
- suffit d'utiliser un enum
- stackoverflow.com/questions/70689/...
Vous devez vous connecter pour publier un commentaire.
Vous êtes à la mise en œuvre de la initialisation modèle où l'instance est créée lors de la première utilisation.
Mais il y a un truc simple qui vous permet de coder un des threads mise en œuvre que n'est pas nécessitent une synchronisation! Il est connu comme le l'Initialisation sur demande du titulaire de l'idiome, et il ressemble à ceci:
Ce code initialise l'instance sur le premier appel de
getInstance()
, et, surtout, il n'a pas besoin de synchronisation en raison du contrat de la classe loader:Holder
s'accès se fait exclusivement à l'intérieur de lagetInstance()
méthode)Holder
's statique bloc de feux)C'est un très joli petit truc que j'utilise à chaque fois que j'ai besoin d'initialisation. Vous bénéficiez également de la bonification d'un
final
exemple, même si c'est créé paresseusement. Notez également comment propre et simple, le code est.Edit: Vous devez définir tous les constructeurs privés ou protégés. Réglage à vide et le constructeur privé va faire le travail
Holder
, pas à l'extérieur de la classeCassandraAstyanaxConnection
. Cette mise en œuvre ne change pas l'API, sauf à supprimer lasynchronized
mot clé degetInstance()
, améliorant ainsi les performances de l'accès à l'instance.static synchronized initialize(MyParam x)
qui ne peut être appelé qu'une seule fois, et ontgetInstance()
retourner l'instance créée eninitialize()
Holder
neINSTANCE = MyClass.create();
et ajouterprivate static MyClass create() {return new MyClass();}
, mais qui serait de pure forme; fait d'éviter l'arbitraire d'un style à la règle mais en ajoutant pas de valeur réelle. Mieux pour l'ignorer.Void
et muter en une Chaîne de caractères. Cela ne veut pas dire "le code est brisé".keyspace
etemp_cf
sont thread-safe (ex. immuable).toutes les méthodes ci-dessus sont très initialisation de l'objet. comment à ce sujet. Cela vous aidera à initialiser ur de la classe paresseusement. Vous pouvez avoir un objet lourd et vous ne voulez pas à s'initialiser au démarrage.
volatile
mot-clé et dans 99,99% des cas, il faudra encore travailler. À mon humble avis il est préférable d'utiliser d'autres modèles qui requièrent le moins de code (par exemple, enum)Pas, ce n'est pas thread-safe si les valeurs retournées sur le pulbic méthodes sont changeble objets.
À cette classe Thread-safe est un moyen de le changer immuable.
Pour ce faire, vous pouvez changer cette méthode comme ceci:
Dans ce livre Java de la Simultanéité dans la Pratique vous pouvez le voir, le principe de l'immutabilité.
Comme mentiond dans cet excellent article ici :
Non, ce n'est pas apparaissent être thread-safe. Il semble que vous il y a mutable données accessibles après l'appel à
getInstance
, où le verrou aurait été publié.Après java version 1.5, nous pouvons utiliser volatile. Si nous avons utilisé volatils java clé de la paroisse, nous pouvons créer singlton classe avec thread-safe, Parce que la variable d'instance, de partager avec les Autres fil ainsi.
Je pense que cela va faire la même chose sans avoir à vérifier par exemple à chaque fois. statique est la même que de vérifier la première fois
static Singl _instance = new Singl();
2) vous n'avez pas indiquer qu'il est désireux d'initialisation, par opposition à un paresseux qui est indiqué dans la questiongetInstance
invocations. Penser à elle, vous pouvez innocemment reportez-vousSingl.class
et boom! l'initialisation est là, même si vous n'essayez même pas d'invoquergetInstance