2016-01-05 2 views
0

Je travaille sur une servlet où je dois fournir une requête unique à chaque requête et stocker chaque paramètre de requête dans une table d'audit. Je suis inquiet des opérations de lecture corrompues sur les tables de base de données si j'essaie d'incrémenter une valeur en regardant en arrière la table pour l'ID précédent. Je veux savoir si en utilisant le temps en millisecondes lorsque la demande est arrivée dans le servlet pour résoudre ce problème. Je crains qu'il puisse y avoir une autre requête provenant d'un autre emplacement géographique en même temps pour la même servlet afin que java.lang.System.currentTimeMillis() soit identique pour l'autre requête à venir. La raison qui m'a fait poster ce doute est que je crois que le comportement multithread du servlet est de prendre une requête à la fois et ensuite d'étendre les cycles de cpu pour chaque requête basée sur un algorithme.création d'un identifiant de requête unique pour chaque requête en utilisant la méthode timemillis dans le servlet

+1

Si vous aviez un bloc de code synchronisé, où vous avez obtenu votre clé, alors vous pouvez contrôler cela. –

+0

Merci d'avoir soulevé des questions sur les blocs de synchronisation, mais je suis inquiet des problèmes de performance, alors je pensais seulement si nous pouvions utiliser le temps en millis. Quel est votre commentaire sur la valeur java.lang.System.currentTimeMillis() pour qu'elle soit unique pour différentes requêtes arrivées en même temps pour la même servlet. – user1036204

+1

Le temps en millisecondes n'est pas garanti pour être unique. Sur certains OS, il peut même s'incrémenter en plus gros morceaux. – Henry

Répondre

2

Le System.currentTimeMillis() n'est pas garanti d'être unique lorsqu'il est appelé par plusieurs threads. Face à cette situation dans le passé, je l'ai utilisé pour créer un AtomicLong ids unique - devrait être verrouillage sans getAndIncremenet de cette classe (et donc raisonnablement efficace) sur la plupart des JVMs

public class IdUtil { 
    private static final AtomicLong counter = new AtomicLong(System.currentTimeMillis()); 

    // return a single id 
    public static long getId() { 
     return counter.getAndIncrement(); 
    } 

    // return a block of ids 
    public static Queue<Long> getIds(long span) { 
     long max = counter.addAndGet(span); 
     Queue<Long> queue = new ArrayDeque<>(span); 
     for(int i = max - span; i < max; i++) { 
      queue.add(i); 
     } 
    } 
} 
0

Même synchronisé il est faux. Vous pouvez obtenir le même identifiant pour deux demandes très proches dans le temps. Vous devriez mieux utiliser un nombre aléatoire long ou séquentiel.

private static final Random r = new Random(); // <- shared resource 
// ... 
long id = r.nextLong(); 

ou

private static final AtomicLong counter = new AtomicLong(System.currentTimeMillis()); // <- shared resource 
// ... 
long id = counter.getAndIncrement(); 

counter est initialisé avec millisecondes il ne fournit pas la même séquence d'id après le redémarrage du programme.

+0

Intéressant maintenant j'ai eu une nouvelle façon après avoir lu votre commentaire, Si j'utilise la méthode ci-dessus, y at-il une chance qu'un jour je reçois le même id pour deux différents demandes à des dates différentes. Dans ce cas, je peux utiliser cet ID et cet horodatage comme une clé unique pour identifier une requête unique. – user1036204

+0

Il y a 18 446 744 073 709 551 616 valeurs longues différentes. Le risque de collision d'identification est vraiment vraiment très bas. Vous auriez besoin de traiter des milliards de transactions chaque jour et la chance serait encore assez faible. – aalku