7
votes

Collection simultanée à 50/50 lire / écrire

J'ai besoin de vos conseils. Pour un début, je voudrais décrire des conditions préalables.

  1. J'ai des objets Java tiers avec défaut java.lang.Object 's hashcode () et est égal () implémentation. L'interface comparable n'est pas implémentée. La taille est insignifiante.
  2. Je dois stocker de tels objets pendant un certain temps en mémoire. Je vais lire et écrire de différents threads au ratio 50/50 (environ 50% des lectures et 50% écrit).
  3. L'ordre des objets n'est pas important. Je veux juste avoir la possibilité de prendre un objet du magasin, c'est tout. Avec prendre je veux dire à la fois obtenir et supprimer en même temps.
  4. Bien sûr, je veux que cela fonctionne aussi vite que possible avec une consommation de mémoire la plus faible. J'essaie d'éviter les synchronisations de mon code.

    Tout d'abord j'ai essayé de résoudre ce problème par moi-même. J'ai immédiatement rejeté CopyOnwriDearray * Collections en raison de la consommation de mémoire élevée. J'ai lu qu'il est préférable de les utiliser en cas d'écrivies rares. Concurrenthashmap dans General Suites pour mes besoins, mais je n'ai pas trouvé de place à faire prendre opération Atomic sans synchronisation. Je me suis arrêté avec mon enquête sur ConcurrentSkiplistset Collection. Il contient pollfirst la méthode assez bonne avec prendre Objets.

    J'ai implémenté ma solution avec concurrentskiplistset comme une base. J'ai tout fonctionne bien sauf un petit détail. Comme je l'ai mentionné ci-dessus, je travaille avec ne pas implémenter comparable . Donc, pour utiliser la collection choisie, je dois en quelque sorte mettre en œuvre comparateur . Voici ma mise en œuvre de cette interface. Dans cet exemple, j'ai utilisé directement java.lang.Object au lieu de mon type d'objets. J'ai fait cela "cause de la mise en œuvre est complètement la même, la différence n'est que dans une partie générique de la classe. xxx

    inconvénient de cette implémentation est évident. J'ai trouvé qu'il y a Aucune garantie que deux objets différents auront des codes de hachage différents. Dans ce cas, il est possible de perdre des objets qui n'est pas acceptable. J'ai pensé retourner un nombre aléatoire en cas de codes de hachage égaux pour différents objets, mais je ne suis pas sûr qu'il ne casse pas concurrentskiplistset implémentation.

    Concernant la situation décrite Deux questions générales.

    1. est-il possible d'implémenter comparateur pour mon objet sous telle sorte de ne pas retourner 0 pour différents objets et conserver concurrentskiplistset opérabilité ?
    2. Y a-t-il une autre façon de stocker mes objets?

      Merci d'avance pour vos réponses.


3 commentaires

Quelle est la taille de vos objets? La stratégie CopyOnwrite est la meilleure si vous avez <100 objets, en raison de la lourdeur de sémaphore. Et si vos collections ne sont pas trop grandes, vous pouvez tout adapter à la génération Eden avec l'algorithme très efficace.


@Taky La taille de la collection n'est pas spécifiée. Cela pourrait être 100 ou 10k. Je ne sais pas. J'essaie de trouver une manière générale de résoudre ce problème. De plus, je n'ai pas attrapé la deuxième partie de votre commentaire. Qu'entendez-vous avec "Eden Generation"?


Par "Eden Generation", je veux dire jeune piscine d'objet JVM.


3 Réponses :


1
votes

1: Vous pouvez implémenter votre comparateur en tant que tel:

public int compare(Object o1, Object o2) {
    if (o1 == o2) {
        return 0;
    } else {
        int dif = o1.hashCode() - o2.hashCode();
        if (dif != 0) {
            return dif;
        } else {
            return 1; //Might cause issues
        }
    }
}


4 commentaires

1. J'ai mentionné une telle mise en œuvre dans ma question. Êtes-vous sûr qu'il ne cassera pas concurrentskiplistset logique? 2. Oui, c'est une bonne option. Mais en cas de synchronisation de charge élevée entraînera des problèmes de performance. J'essaie de l'éviter.


@Art hm je suis mal lu sur le comparateur. Je suppose que vous pouvez également mettre chaque objet dans une enveloppe comparable avec un index basé sur l'ordre dans lequel ils ont été créés. Cela fonctionnerait-il?


En général, cela devrait fonctionner. Mais la mise en œuvre sera assez complexe. Par exemple, je dois utiliser faiblicielle dans ce cas ne dépend pas de l'objet lui-même. En tant que solution technique de ce problème, cela fonctionne, mais de mon point de vue, il semble très moche. Quoi qu'il en soit, merci à l'idée!


Le "pourrait" dans "pourrait causer des problèmes" est faux. Cela causera des problèmes car les lishlistes ont besoin d'un ordre total de ses éléments et cela le violent clairement (il est également brisé dans 50% de tous les cas même si le hashcode était unique - la soustraction des comparaisons ne fonctionne pas)



3
votes

Vous recherchez probablement ConcurrentLinkedQueue , cela stockera les articles basés sur la commande FIFO (premier en première sortie). En raison de ce no hashcode et Les exigences comparables sont présentes. La mise en œuvre de cette file d'attente est très efficace, sans aucun verrouillage interne.

Une difficulté que vous avez (lorsque vous n'utilisez pas les verrous) est que vous ne pouvez pas vérifier si la collection n'est pas vide, puis en prends une (car elle aurait peut-être changé après votre chèque et avant votre action). Par conséquent, la fonction prend retournera null lorsque rien n'est présent. Si vous ne voulez pas continuer à interroguer pour les données, vous pouvez également recourir à des cours en mettant en œuvre le blockingQueue interface, cela offre des fonctions qui attendent que les données soient disponibles.


0 commentaires

1
votes

Concourshashmap dans des suites générales pour mes besoins, mais je n'ai pas trouvé moyen de faire fonctionner Atomic

Pourquoi ne pas utiliser Supprimer dans ConcourshashMap? Semble que c'est ce dont vous avez besoin.


1 commentaires

Mais pour utiliser supprimer la méthode , je dois d'abord obtenir un objet d'abord. Je peux le faire avec itérateur essayer de supprimer chaque objet jusqu'à ce que je réussirai. S'il y a beaucoup de threads, cela prendra beaucoup de temps à essayer de supprimer déjà les entrées supprimées. C'est parce que via itérateur de Concurrenthashmap Vous travaillez avec un état de la carte, mais pas avec les données réelles. Du site opposé pollfirst () méthode de Concurantskiplistset fonctionnant avec les données réelles. Dans ce cas, il devrait être beaucoup plus rapide.