Traitement simultané


1. [Obligatoire] L'obtention d'un objet singleton doit garantir la sécurité des threads, et les méthodes doivent également garantir la sécurité des threads.

Remarque : Les classes basées sur les ressources, les classes d'outils et les classes d'usine singleton nécessitent toutes une attention particulière.

2. [Obligatoire] Veuillez spécifier un nom de thread significatif lors de la création d'un thread ou d'un pool de threads pour faciliter le traçage lorsqu'une erreur se produit.

Exemple positif :

public class TimerTaskThread extends Thread {
public TimerTaskThread(){
super.setName("TimerTaskThread"); ...
}

3. [Obligatoire] Les ressources de thread doivent être fournies via le pool de threads et la création explicite de threads dans l'application n'est pas autorisée.

Explication : L'avantage d'utiliser un pool de threads est de réduire le temps passé à créer et à détruire les threads ainsi que la surcharge des ressources système, et de résoudre le problème des ressources insuffisantes. Si le pool de threads n'est pas utilisé, le système peut créer un grand nombre de threads similaires, entraînant une consommation de mémoire ou des problèmes de « commutation excessive ».

4. [Obligatoire] Les pools de threads ne peuvent pas être créés à l'aide d'exécuteurs, mais via ThreadPoolExecutor. Cette
méthode de traitement permet aux étudiants en rédaction d'être plus clairs sur les règles de fonctionnement du pool de threads et d'éviter le risque. d'épuisement des ressources.

Explication : Les inconvénients de l'objet pool de threads renvoyés par

Executors sont les suivants :

1) FixedThreadPool

et

SingleThreadPool  : La longueur de file d'attente de requêtes autorisée est Integer.MAX_VALUE, ce qui peut accumuler une grande quantité nombre de requêtes, ce qui entraîne un MOO.

2)

CachedThreadPool

et

ScheduledThreadPool :Le nombre de threads autorisés à être créés est Integer.MAX_VALUE, ce qui peut créer un grand nombre de threads, ce qui entraîne un MOO.

5. [Obligatoire] SimpleDateFormat est une classe non sécurisée pour les threads. Généralement, elle ne doit pas être définie comme une variable statique. Si elle est définie comme
static, elle doit être verrouillée ou utiliser la classe d'outils DateUtils.

Exemple positif :

Faites attention à la sécurité des threads et utilisez DateUtils. Le traitement suivant est également recommandé :

private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
@ Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
Remarque :

S'il s'agit d'une application JDK 8, vous pouvez utiliser Instant au lieu de Date, LocalDateTime au lieu de Calendar,

DateTimeFormatter au lieu de Simpledateformatter, l'explication officielle : simple beautiful strong fil immuable - sûr.

6. [Obligatoire] Lorsque la concurrence est élevée, les appels synchrones doivent prendre en compte la perte de performances des verrous. Si vous pouvez utiliser des structures de données sans verrouillage, n'utilisez pas de verrous ; si vous pouvez verrouiller des blocs, ne verrouillez pas l'intégralité du corps de la méthode ; si vous pouvez utiliser des verrous d'objet, n'utilisez pas de verrous de classe.

7. [Obligatoire] Lorsque vous verrouillez plusieurs ressources, tables de base de données et objets en même temps, vous devez maintenir un ordre de verrouillage cohérent, sinon cela pourrait provoquer un blocage.

Explication : Le thread un doit verrouiller toutes les tables A, B et C dans l'ordre avant de pouvoir effectuer l'opération de mise à jour. Ensuite, l'ordre de verrouillage du thread deux doit également être A, B et C, sinon il y a un blocage. peut se produire.


8. [Obligatoire] Lors de la modification simultanée du même enregistrement, pour éviter la perte de mise à jour, verrouillez-le au niveau de la couche d'application, verrouillez-le dans le cache ou utilisez le verrouillage optimiste au niveau de la

couche de base de données et utilisez la version. comme base de mise à jour.

Remarque :

Si la probabilité de conflit par accès est inférieure à 20 %, il est recommandé d'utiliser le verrouillage optimiste, sinon d'utiliser le verrouillage pessimiste. Le nombre de tentatives de verrouillage optimiste ne doit pas être inférieur à 3 fois.

9. [Obligatoire] Lorsque plusieurs threads traitent des tâches planifiées en parallèle, lorsque Timer exécute plusieurs TimeTasks, tant que l'une d'entre elles n'attrape pas l'exception levée

, les autres tâches se termineront automatiquement. le cas lors de l'utilisation de la question ScheduledExecutorService.

10. [Recommandation] Utilisez CountDownLatch pour effectuer des opérations asynchrones à synchrones. Chaque thread doit appeler la méthode countDown


avant de quitter. Faites attention à intercepter les exceptions lors de l'exécution du code dans le thread pour vous assurer que la méthode countDown peut. être exécuté pour éviter de ne pas pouvoir exécuter le thread principal

À la méthode countDown, le résultat ne sera renvoyé qu'après expiration du délai.

Remarque :

Notez que la pile d'exceptions levée par le thread enfant ne peut pas être atteinte par try - catch dans le thread principal.

11. [Recommandé] Évitez que les instances aléatoires soient utilisées par plusieurs threads. Bien que le partage de cette instance soit thread-safe, cela entraînera une dégradation des performances en raison de la concurrence pour la même

seed.

Explication : Les instances aléatoires incluent les instances java util Random ou Math random() .

Exemple positif : Après JDK 7, vous pouvez utiliser directement l'API ThreadLocalRandom. Avant JDK 7, vous pouvez obtenir une instance par

thread.

12. [Recommandation] Utilisez un verrouillage à double vérification (dans des scénarios simultanés) pour optimiser les dangers cachés d'une initialisation retardée (voir la déclaration « Le verrouillage à double vérification est rompu ), recommandé La solution la plus simple au problème.


(applicable au JDK 5 et supérieur) consiste à déclarer la propriété cible comme volatile.

Contre exemple :

class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) synchronized(this) {
if (helper == null)
helper = new Helper();
}
return helper;
}
// other functions and members...
}

13. [Référence] volatile résout le problème de l'invisibilité de la mémoire multithread. Pour une écriture et plusieurs lectures, le problème de synchronisation des variables peut être résolu, mais s'il y a plusieurs écritures, le problème de sécurité des threads ne peut pas être résolu. S'il s'agit d'une opération count ++, utilisez la classe suivante pour l'implémenter : AtomicInteger count = new AtomicInteger(); count . S'il s'agit du JDK 8, il est recommandé d'utiliser l'objet LongAdder, qui. a de meilleures performances qu'AtomicLong (réduisez l'optimisme du nombre de tentatives de verrouillage).

14. [Référence] Lorsque HashMap a une capacité de redimensionnement insuffisante, des liens morts peuvent survenir en raison d'une concurrence élevée, provoquant une surtension du processeur. Veuillez faire attention pour éviter ce risque pendant le processus de développement.

15. [Référence] ThreadLocal ne peut pas résoudre le problème de mise à jour des objets partagés. Il est recommandé d'utiliser la modification statique

pour les objets ThreadLocal. Cette variable est commune à toutes les opérations au sein d'un thread, elle est donc définie comme une variable statique. Toutes ces instances partagent cette variable statique, ce qui signifie qu'elle est chargée lorsque la classe est utilisée pour la première fois et uniquement une partie de l'espace de stockage. est alloué. Les objets de la classe (uniquement définis dans ce thread) peuvent manipuler cette variable.