2016-09-07 1 views
3

J'ai une situation que j'ai rencontrée à plusieurs reprises, où plusieurs classes de différentes parties de l'architecture veulent regarder la même structure de données, qui peut être entièrement remplacée (pour Par exemple, quand une nouvelle version vient du réseau.) Si je garde la structure de données et mettre à jour l'information qui est assez facile (tout peut référencer le même, et obtiendra l'information mise à jour quand ils regardent), mais si la référence est entièrement réattribuée, ce qui n'est pas reflété ailleurs.Version Java de "Pointer Pointer"

J'ai eu une idée de faire un emballage super-générique comme:

public class Wrapper<T>{ 
    public T _value; 
} 

Avec l'idée que vous ne réattribuer l'emballage, juste la valeur à l'intérieur. Tous les différents composants pourraient alors pointer vers l'enveloppe, et la valeur interne pourrait être réaffectée proprement lorsqu'une "nouvelle" version est arrivée. (Je pense que j'ai vu cela fait avec ** en C.)

Mais, je me méfie que je n'ai jamais vu cela auparavant. Y a-t-il une meilleure façon de résoudre ce problème?

+5

[ 'AtomicReference'] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomic/AtomicReference.html) peut être un bon choix, de sorte que vous êtes assuré des lectures à jour sur plusieurs threads. –

+0

En outre, pensez à ajouter le champ 'version' à l'instance de structure de données pouvant être mise à jour, afin que les observateurs puissent détecter si les données ont été mises à jour lorsqu'elles examinaient autre chose. –

Répondre

2

Utilisez AtomicReference.

String initialReference = "initial value referenced"; 

AtomicReference<String> atomicStringReference = 
    new AtomicReference<String>(initialReference); 

String newReference = "new value referenced"; 
//directly update 
atomicReference.set(newReference); 

//compare and set 
boolean exchanged = atomicStringReference.compareAndSet(initialReference, newReference); 
System.out.println("exchanged: " + exchanged); 

exchanged = atomicStringReference.compareAndSet(initialReference, newReference); 
System.out.println("exchanged: " + exchanged); 

//get value 
String reference = atomicReference.get(); 

exemple de code de here

+0

Je suis allé avec ça, même si je me sens un peu coupable, puisque la chose que je représente n'est pas strictement immuable (parfois je la modifie, parfois je veux la remplacer) –

+0

@EdwardPeters alors quoi? La partie du pointeur du pointeur fonctionnera. Si votre objet est modifiable et que vous travaillez avec un environnement multithread, vous devrez également gérer la concurrence. Vous pouvez également utiliser AtomicReference pour les champs modifiables de votre classe. – Bohemian

+0

@Bohemian Ouais, je me suis synchronisé dessus, mais la documentation que j'ai lue pour 'AtomicReference' dit beaucoup" Immuable ", donc je crains de rompre un contrat quelque part. –