2011-04-21 3 views
0

J'utilise Java 6 Collecetions API. J'ai besoin d'une collection qui ne devrait avoir que N éléments. Je veux dire que si j'ajoute un nouvel élément et que la collection contient déjà N éléments, le dernier élément doit être supprimé et un nouveau doit être ajouté dans la tête de collection. Je suivant fragment de code pour le faire:LinkedList.pollLast() throws NullPointerException

class A { 

    int N = 100; 
    Deque dq = new LinkedList(); 

    void add(Object o) { 
    synchronized (o) { 
     if (dq.size() == N) { 
     dq.pollLast(); 
     } 
     dq.add(o); 
    } 
    } 

    Deque getDq() { 
    return new LinkedList(dq); 
    } 
} 

objet de type A peut être consulté de nombreux utilisateurs dans le même temps d'ajouter de nouveaux éléments. En pratique, je suis arrivé NullPointerException avec elle:

Caused by: java.lang.NullPointerException 
    at java.util.LinkedList.remove(LinkedList.java:790) 
    at java.util.LinkedList.removeLast(LinkedList.java:144) 
    at java.util.LinkedList.pollLast(LinkedList.java:573) 
    at A.add(A.java:9) 

contrat Deque.pollLast() ne dit rien au sujet NullPointerException:

Rapporte et supprime le dernier élément de cette liste, ou renvoie null si cette liste est vide.

L'ajout d'éléments est également synchronisé.

Est-ce que quelqu'un sait ce que pourrait être la raison d'exception?

Merci pour toutes les idées

+1

Vous devez synchroniser sur un objet commun (à savoir la liste, 'this' ou un objet de verrouillage spécial), et non sur le paramètre. Aucune idée si cela cause votre problème, cependant. –

+2

Est-ce le code que vous utilisez?Si oui, dans quelle langue courez-vous? 'Dequeu' n'a pas de champ public' size' auquel vous pourriez accéder comme ça. –

+2

@user: c'est une méthode, vous y accédez sans le '()'. Je suis conscient que c'est probablement une faute de frappe, mais cela signifie que le code que vous nous montrez n'est pas ** le code qui a le problème. S'il vous plaît produire un [SSCCE] (http://sscce.org/). –

Répondre

3

Je suppose que la syncronisation est faite sur le mauvais objet! Il devrait être dq mais pas o!

... synchronized (dg) { ... 
+0

Je suis d'accord là-dessus. Vous n'empêchez pas l'accès simultané à votre Deque en verrouillant l'élément que vous essayez d'ajouter/supprimer. – merxbj

0

voir this javadoc il dit

Removes and returns the last element from this list. 

d'abord il supprime l'objet si elle est nulle jette alors NullPointerException: méthode

donc faire add (..) synchronisé et vérifier la taille avant dq.pollLast();

+0

[LinkedList.pollLast()] (http://download.oracle.com/javase/6/docs/api/java/util/LinkedList.html#pollLast()) ne lance pas d'exception si le code est bien synchronisé: – Raman

1

J'ai couru votre code d'ajouter à l'aide du test suivant

A a = new A(); 
    for (int i = 0; i < 200; i++) 
    { 
     a.add(i); 
    } 
    System.out.println(a.dq); 

Et tout semble fonctionner correctement. Pouvez-vous fournir plus de détails sur l'état de l'application lorsque vous obtenez le NPE? Quel est l'objet que vous essayez d'ajouter? Quel est l'état de la file d'attente à ce moment-là?

En outre, vous avez mentionné

si j'ajouter un nouvel élément et collection ont déjà N éléments que le dernier élément doit être enlevé et nouveau ajouter dans la tête de collection

Votre code ne le fait pas. En ce moment, il ajoute à la queue de la collection. Pour ajouter à la tête, changer

dq.add(o) 

à

dq.addFirst(o) 
+0

Je pense que le vrai problème ici est la synchronisation, pas l'algorithme lui-même. Cela peut aussi être faux. – merxbj

+0

Très vrai. J'essayais d'écarter les problèmes d'algorithme, et je demandais de plus amples informations sur la façon dont dq est utilisé et quel est son état. Probablement dq est utilisé d'une autre manière non synchronisée via l'accesseur getDq() (comme d'autres l'ont mentionné). – tschaible

Questions connexes