Maison >Java >JavaQuestions d'entretien >Questions d'entretien multithread Java qui valent la peine d'être collectées (avec réponses)
Cet article résume pour vous quelques questions et réponses d'entretien multithread Java. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer. J'espère qu'il sera utile à tout le monde.
Qu'est-ce qu'un fil de discussion ?
Le thread est la plus petite unité que le système d'exploitation peut effectuer la planification des opérations. Il est inclus dans le processus et constitue l'unité opérationnelle réelle du processus. Les programmeurs peuvent l'utiliser pour la programmation multiprocesseur, et vous pouvez utiliser le multithreading pour accélérer les tâches gourmandes en calcul. Par exemple, s'il faut 100 millisecondes à un thread pour terminer une tâche, alors il ne faut que 10 millisecondes pour utiliser dix threads pour terminer la tâche. Java offre un excellent support du multithreading au niveau du langage, ce qui constitue également un bon argument de vente.
2) Quelle est la différence entre thread et processus ?
Les threads sont un sous-ensemble de processus. Un processus peut avoir plusieurs threads, et chaque thread effectue différentes tâches en parallèle. Différents processus utilisent différents espaces mémoire et tous les threads partagent le même espace mémoire. Ne confondez pas cela avec la mémoire de pile. Chaque thread possède sa propre mémoire de pile pour stocker les données locales.
3) Comment implémenter les threads en Java ?
Il existe deux manières au niveau linguistique. Une instance de la classe java.lang.Thread est un thread, mais elle doit appeler l'interface java.lang.Runnable pour s'exécuter. Puisque la classe thread elle-même est l'interface Runnable appelée, vous pouvez hériter de la classe java.lang.Thread. ou appelez directement l'interface Runnable pour la remplacer. Écrivez la méthode run() pour implémenter les threads.
4) Utiliser Runnable ou Thread ?
Cette question fait suite à la question précédente. Tout le monde sait que nous pouvons implémenter des threads en héritant de la classe Thread ou en appelant l'interface Runnable. Quand est-il utilisé ? Il est facile de répondre à cette question si vous savez que Java ne prend pas en charge l'héritage multiple de classes, mais vous permet d'appeler plusieurs interfaces. Donc si vous souhaitez hériter d'autres classes, vous devez bien sûr appeler l'interface Runnable.
6) Quelle est la différence entre les méthodes start() et run() dans la classe Thread ?
Cette question est souvent posée, mais elle permet toujours de distinguer la compréhension de l'intervieweur du modèle de thread Java. La méthode start() est utilisée pour démarrer un thread nouvellement créé, et start() appelle en interne la méthode run(), ce qui a un effet différent de celui de l'appel direct de la méthode run(). Lorsque vous appelez la méthode run(), elle ne sera appelée que dans le thread d'origine. Si aucun nouveau thread n'est démarré, la méthode start() démarrera un nouveau thread.
7) Quelle est la différence entre Runnable et Callable en Java ?
Runnable et Callable représentent tous deux des tâches à exécuter dans différents threads. Runnable est disponible depuis JDK1.0 et Callable a été ajouté dans JDK1.5. La principale différence entre eux est que la méthode call() de Callable peut renvoyer des valeurs et lever des exceptions, tandis que la méthode run() de Runnable n'a pas ces fonctions. Callable peut renvoyer un objet Future chargé avec les résultats du calcul.
8) Quelle est la différence entre CyclicBarrier et CountDownLatch en Java ?
CyclicBarrier et CountDownLatch peuvent être utilisés pour faire en sorte qu'un groupe de threads attende d'autres threads. Contrairement à CyclicBarrier, CountdownLatch ne peut pas être réutilisé.
9) Qu'est-ce que le modèle de mémoire Java ?
Le modèle de mémoire Java spécifie et guide les programmes Java pour qu'ils se comportent de manière déterministe sur différentes architectures de mémoire, processeurs et systèmes d'exploitation. C’est particulièrement important dans les situations multithread. Le modèle de mémoire Java garantit que les modifications apportées par un thread peuvent être visibles par les autres threads et qu'il existe une relation de priorité entre eux. Cette relation définit certaines règles pour permettre aux programmeurs de réfléchir plus clairement lorsqu'ils programment simultanément. Par exemple, la relation d'anticipation garantit que :
Je vous recommande fortement de lire le chapitre 16 de « Pratique de programmation simultanée Java » pour approfondir votre compréhension du modèle de mémoire Java.
10) Que sont les variables volatiles en Java ?
volatile est un modificateur spécial qui ne peut être utilisé que par les variables membres. En l'absence de classes de synchronisation dans les programmes concurrents Java, les opérations multithread sur les variables membres sont transparentes pour les autres threads. Les variables volatiles peuvent garantir que la prochaine opération de lecture aura lieu après l'opération d'écriture précédente, ce qui est la règle des variables volatiles dans la question précédente.
11) Qu'est-ce que la sécurité des fils ? Vector est-il une classe thread-safe ?
S'il y a plusieurs threads exécutés en même temps dans le processus où se trouve votre code, ces threads peuvent exécuter ce code en même temps. Si les résultats de chaque exécution sont les mêmes que ceux des exécutions monothread et que les valeurs des autres variables sont les mêmes que celles attendues, cela est thread-safe. Une classe de compteur thread-safe ne provoquera pas d’erreurs de calcul lorsque le même objet d’instance est utilisé par plusieurs threads. Évidemment, vous pouvez diviser les classes de collection en deux groupes, thread-safe et non-thread-safe. Vector utilise des méthodes synchronisées pour assurer la sécurité des threads, tandis qu'ArrayList, qui lui est similaire, n'est pas thread-safe.
12) Qu'est-ce qu'une condition de concurrence en Java ? Donnez un exemple.
Les conditions de course provoqueront quelques bugs dans le programme dans des conditions concurrentes. Des conditions de concurrence se produiront lorsque plusieurs threads se disputeront certaines ressources. Si le programme à exécuter en premier ne parvient pas à rivaliser et est exécuté plus tard, des bogues incertains apparaîtront dans l'ensemble du programme. De tels bugs sont difficiles à trouver et se reproduisent en raison de la concurrence aléatoire entre les threads.
13) Comment arrêter un thread en Java ?
Java fournit une API riche mais ne fournit pas d'API pour arrêter les threads. Le JDK 1.0 disposait à l'origine de certaines méthodes de contrôle telles que stop(), suspend() et Ensure(), mais elles ont été obsolètes dans les versions ultérieures du JDK en raison de menaces potentielles de blocage. Après cela, les concepteurs de l'API Java n'ont pas fourni de compatibilité et de thread-. moyen sûr d'arrêter un fil de discussion. Le thread se terminera automatiquement lorsque la méthode run() ou call() sera exécutée. Si vous souhaitez terminer manuellement un thread, vous pouvez utiliser une variable booléenne volatile pour quitter la boucle de la méthode run() ou annuler la tâche pour interrompre le thread. .
14) Que se passe-t-il si une exception se produit pendant qu'un thread est en cours d'exécution ?
Il s'agit d'une question d'entretien Java très délicate que j'ai rencontrée lors d'une interview. En termes simples, si l'exception n'est pas interceptée, le thread cessera de s'exécuter. Thread.UncaughtExceptionHandler est une interface intégrée utilisée pour gérer les interruptions soudaines des threads causées par des exceptions non interceptées. Lorsqu'une exception non interceptée entraîne l'interruption d'un thread, la JVM utilise Thread.getUncaughtExceptionHandler() pour interroger le UncaughtExceptionHandler du thread et transmet le thread et l'exception en tant que paramètres à la méthode uncaughtException() du gestionnaire pour traitement.
15) Comment partager des données entre deux threads ?
Vous pouvez y parvenir grâce à des objets partagés ou en utilisant des structures de données concurrentes comme des files d'attente de blocage. Ce tutoriel "Java Inter-Thread Communication" (impliquant le partage d'objets entre deux threads) utilise les méthodes wait et notify pour implémenter le modèle producteur-consommateur.
16) Quelle est la différence entre notify et notifyAll en Java ?
C'est une autre question délicate, car plusieurs threads peuvent attendre un seul verrouillage de moniteur. Les concepteurs de l'API Java fournissent certaines méthodes pour les avertir lorsque les conditions d'attente changent, mais ces méthodes ne sont pas entièrement disponibles. mis en œuvre. La méthode notify() ne peut pas réveiller un thread spécifique, elle n'est donc utile que lorsqu'un thread est en attente. Et notifyAll() réveille tous les threads et leur permet de rivaliser pour le verrou afin de garantir qu'au moins un thread peut continuer à s'exécuter.
17) Pourquoi les méthodes wait, notify et notifyAll ne sont-elles pas dans la classe thread ?
Il s'agit d'une question liée à la conception qui examine le point de vue de l'intervieweur sur les systèmes existants et certaines choses courantes mais apparemment déraisonnables. Lorsque vous répondez à ces questions, vous devez expliquer pourquoi il est logique de placer ces méthodes dans la classe Object et pourquoi ne pas les mettre dans la classe Thread. Une raison évidente est que les verrous fournis par JAVA se situent au niveau de l'objet plutôt qu'au niveau du thread. Chaque objet possède un verrou et est obtenu via le thread. Si le thread doit attendre un verrou, il est logique d'appeler la méthode wait() dans l'objet. Si la méthode wait() est définie dans la classe Thread, il n'est pas évident de savoir quel verrou le thread attend. En termes simples, puisque wait, notify et notifyAll sont des opérations au niveau du verrou, elles sont définies dans la classe Object car les verrous appartiennent aux objets.
18) Qu'est-ce qu'une variable ThreadLocal ?
ThreadLocal est une variable spéciale en Java. Chaque thread a un ThreadLocal, ce qui signifie que chaque thread a sa propre variable indépendante et que la condition de concurrence critique est complètement éliminée. C'est un bon moyen d'obtenir la sécurité des threads pour les objets coûteux à créer. Par exemple, vous pouvez utiliser ThreadLocal pour sécuriser les threads SimpleDateFormat, car cette classe est coûteuse à créer et nécessite la création d'une instance différente pour chaque appel, cela ne vaut donc pas la peine de l'avoir. portée locale En l'utilisant, si chaque thread dispose de sa propre copie unique de la variable, l'efficacité sera grandement améliorée. Premièrement, le nombre d’objets coûteux créés est réduit grâce à la réutilisation. Deuxièmement, vous bénéficiez de la sécurité des threads sans utiliser de synchronisation ou d’immuabilité coûteuse. Un autre bon exemple de variables locales de thread est la classe ThreadLocalRandom, qui réduit le nombre d'objets Random coûteux à créer dans un environnement multithread.
19) Qu'est-ce que FutureTask ?
Dans les programmes concurrents Java, FutureTask représente une opération asynchrone qui peut être annulée. Il dispose de méthodes telles que le démarrage et l'annulation d'opérations, la requête si les opérations sont terminées et la récupération des résultats des opérations. Le résultat ne peut être récupéré que lorsque l'opération est terminée. Si l'opération n'est pas terminée, la méthode get se bloquera. Un objet FutureTask peut envelopper des objets qui appellent Callable et Runnable. Puisque FutureTask appelle également l'interface Runnable, il peut être soumis à l'Executor pour exécution.
20) Quelle est la différence entre les méthodes interrompues et isInterruptedd en Java ?
La principale différence entre interrompu() et isInterrupted() est que le premier effacera l'état d'interruption et le second non. Le mécanisme d'interruption du multithreading Java est implémenté à l'aide d'indicateurs internes. L'appel de Thread.interrupt() pour interrompre un thread définira l'indicateur d'interruption sur true. Lorsque le thread d'interruption appelle la méthode statique Thread.interrupted() pour vérifier l'état de l'interruption, l'état de l'interruption sera effacé. La méthode non statique isInterrupted() est utilisée pour interroger l'état d'interruption des autres threads et ne modifie pas l'identifiant de l'état d'interruption. En termes simples, toute méthode qui lève InterruptedException effacera l'état d'interruption. Dans tous les cas, l'état d'interruption d'un thread peut être modifié par d'autres threads appelant des interruptions.
21) Pourquoi les méthodes wait et notify sont-elles appelées dans les blocs synchronisés ?
Principalement parce que l'API Java l'exige, si vous ne le faites pas, votre code lancera une IllegalMonitorStateException. Une autre raison est d'éviter les conditions de course entre l'attente et la notification.
22) Pourquoi devriez-vous vérifier les conditions d'attente en boucle
Les threads en état d'attente peuvent recevoir de fausses alertes et des réveils parasites s'ils ne sont pas vérifiés en boucle ? une condition, le programme se terminera si la condition de fin n’est pas remplie. Par conséquent, lorsqu'un thread en attente se réveille, son état d'attente d'origine ne peut pas être considéré comme toujours valide. Il peut changer pendant la période suivant l'appel de la méthode notify() et avant le réveil du thread en attente. C'est pourquoi l'utilisation de la méthode wait() dans une boucle fonctionne mieux. Vous pouvez créer un modèle dans Eclipse pour appeler wait et notifier pour l'essayer. Si vous souhaitez en savoir plus sur ce problème, je vous recommande de lire le chapitre sur les threads et la synchronisation dans le livre "Effective Java".
23) Quelle est la différence entre les collections synchronisées et les collections simultanées en Java ?
Les collections synchronisées et les collections simultanées fournissent des collections thread-safe appropriées pour le multithread et la concurrence, mais les collections simultanées sont plus évolutives. Avant Java 1.5, les programmeurs ne pouvaient utiliser que des collections synchronisées, ce qui provoquerait des conflits lors de la concurrence multithread et entraverait l'évolutivité du système. Java5 a introduit des collections concurrentes comme ConcurrentHashMap, qui non seulement assurent la sécurité des threads, mais améliorent également l'évolutivité grâce à des techniques modernes telles que la séparation des verrous et le partitionnement interne.
24) Quelle est la différence entre tas et pile en Java ?
Pourquoi cette question est-elle classée comme une question d'entretien multithread et simultanée ? Car la pile est une zone mémoire étroitement liée aux threads. Chaque thread possède sa propre mémoire de pile, qui est utilisée pour stocker les variables locales, les paramètres de méthode et les appels de pile. Les variables stockées dans un thread ne sont pas visibles par les autres threads. Le tas est une zone mémoire commune partagée par tous les threads. Les objets sont tous créés dans le tas. Afin d'améliorer l'efficacité, le thread les mettra en cache depuis le tas vers sa propre pile. Si plusieurs threads utilisent cette variable, cela peut causer des problèmes. Cela nécessite que le thread démarre à partir de la pile principale. Lire la valeur d'une variable depuis la mémoire.
25) Qu'est-ce qu'un pool de threads ? Pourquoi l'utiliser ?
La création de threads coûte cher en ressources et en temps. Si les threads sont créés seulement après l'arrivée d'une tâche, le temps de réponse deviendra plus long et le nombre de threads pouvant être créés par un processus est limité. Afin d'éviter ces problèmes, plusieurs threads sont créés pour répondre au traitement au démarrage du programme. Ils sont appelés pools de threads et les threads à l'intérieur sont appelés threads de travail. À partir du JDK1.5, l'API Java fournit le framework Executor afin que vous puissiez créer différents pools de threads. Par exemple, un seul pool de threads traite une tâche à la fois ; un nombre fixe de pools de threads ou un pool de threads de cache (un pool de threads extensible adapté aux programmes comportant de nombreuses tâches de courte durée).
26) Comment écrire du code pour résoudre le problème producteur-consommateur ?
En réalité, la plupart des problèmes de thread que vous résolvez appartiennent au modèle producteur-consommateur, où un thread produit des tâches que d'autres threads doivent consommer. Vous devez savoir comment communiquer entre les threads pour résoudre ce problème. . La méthode de niveau inférieur consiste à utiliser wait et notify pour résoudre ce problème. La meilleure méthode consiste à utiliser Semaphore ou BlockingQueue pour implémenter le modèle producteur-consommateur.
27) Comment éviter les impasses ?
Deadlock dans le multi-threading Java
L'impasse fait référence à une situation causée par deux ou plusieurs processus en compétition pour les ressources lors de l'exécution. pouvoir avancer sans force extérieure. Il s'agit d'un problème sérieux, car un blocage entraînera le blocage de votre programme et l'empêchera de terminer la tâche. Les quatre conditions suivantes doivent être remplies pour qu'un blocage se produise :
Le moyen le plus simple d'éviter une impasse est d'éviter les conditions d'attente circulaires, de définir des indicateurs et de trier toutes les ressources du système, et de stipuler que tous les processus doivent postuler pour les ressources dans un certain ordre (ordre croissant ou décroissant). ) Effectuez des opérations pour éviter les blocages.
28) Quelle est la différence entre livelock et deadlock en Java ?
Il s'agit d'une extension de la question ci-dessus. Livelock est similaire à un blocage. La différence est que l'état du thread ou du processus dans Livelock peut être considéré comme un type particulier de faim. . Un exemple réaliste de livelock est lorsque deux personnes se rencontrent dans un couloir étroit. Les deux personnes essaient de s'éviter pour pouvoir se passer, mais comme les directions d'évitement sont les mêmes, personne ne peut finalement traverser le couloir. En termes simples, la principale différence entre livelock et deadlock est que dans le premier cas, l'état du processus peut changer mais il ne peut pas continuer à s'exécuter.
29) Comment détecter si un thread possède un verrou ?
Je n'aurais jamais su que nous pouvions détecter si un fil de discussion possédait un verrou jusqu'à ce que je participe à un entretien téléphonique. Il existe une méthode dans java.lang.Thread appelée holdLock(), qui renvoie true si et seulement si le thread actuel détient un verrou sur un objet spécifique.
30) Comment obtenir la pile de threads en Java ?
Il existe plusieurs façons d'obtenir la pile de threads d'un processus Java pour différents systèmes d'exploitation. Lorsque vous obtenez la pile de threads, la JVM enregistre l'état de tous les threads dans un fichier journal ou vers la console. Sous Windows, vous pouvez utiliser la combinaison de touches Ctrl + Break pour obtenir la pile de threads, et sous Linux, utilisez la commande kill -3. Vous pouvez également utiliser l'outil jstack pour l'obtenir, qui fonctionne sur l'ID du thread. Vous pouvez utiliser l'outil jps pour trouver l'ID.
31) Quel paramètre dans JVM est utilisé pour contrôler la taille de la pile du thread ?
Cette question est très simple. Le paramètre -Xss est utilisé pour contrôler le. taille de pile du fil.
32) Quelle est la différence entre synchronisé et ReentrantLock en Java ?
Java n'a pu parvenir à une exclusion mutuelle que grâce au mot-clé synchronisé pendant longtemps, ce qui présente quelques lacunes. Par exemple, vous ne pouvez pas étendre les méthodes ou bloquer les limites en dehors du verrou, vous ne pouvez pas annuler à mi-chemin lorsque vous essayez d'acquérir le verrou, etc. Java 5 fournit un contrôle plus complexe via l'interface Lock pour résoudre ces problèmes. La classe ReentrantLock implémente Lock, qui a la même concurrence et la même sémantique de mémoire que synchronisée, mais est également extensible.
33) Il existe trois threads T1, T2 et T3. Comment s'assurer qu'ils s'exécutent dans l'ordre ?
En multi-threading, il existe de nombreuses façons de laisser les threads s'exécuter dans un ordre spécifique. Vous pouvez utiliser la méthode join() de la classe thread pour démarrer un autre thread dans un thread et dans l'autre. le fil termine le fil et continue l'implémentation. Pour garantir l'ordre des trois threads, vous devez commencer par le dernier (T3 appelle T2, T2 appelle T1), de sorte que T1 termine en premier et T3 en dernier.
34) Quelle est la fonction de la méthode rendement dans la classe Thread ?
La méthode Yield peut suspendre l'objet thread en cours d'exécution et permettre à d'autres threads avec la même priorité de s'exécuter. Il s'agit d'une méthode statique qui garantit uniquement que le thread actuel abandonnera l'occupation du processeur et ne garantit pas que d'autres threads pourront occuper le processeur. Le thread exécutant rendement() peut être à nouveau exécuté immédiatement après être entré dans l'état de pause.
35) Quelle est la concurrence de ConcurrentHashMap en Java ?
ConcurrentHashMap divise la carte réelle en plusieurs parties pour assurer son évolutivité et la sécurité des threads. Cette division est obtenue à l'aide de la concurrence, qui est un paramètre facultatif du constructeur de classe ConcurrentHashMap avec une valeur par défaut de 16 pour éviter les conflits dans les situations multithread.
36) Qu'est-ce que le sémaphore en Java ?
Semaphore en Java est une nouvelle classe de synchronisation, qui est un signal de comptage. Conceptuellement, un sémaphore gère une collection autorisée. Si nécessaire, chaque acquire() bloque jusqu'à ce que l'autorisation soit disponible, puis acquiert l'autorisation. Chaque release() ajoute une autorisation, libérant ainsi potentiellement un acquéreur bloquant. Cependant, au lieu d'utiliser de véritables objets de licence, Semaphore ne compte que le nombre de licences disponibles et prend les mesures appropriées. Les sémaphores sont souvent utilisés dans le code multithread, tel que les pools de connexions de bases de données.
37) Si la file d'attente du pool de threads est pleine lorsque vous soumettez la tâche. Que se passe-t-il lorsque la réunion a lieu ?
C'est une question délicate, et de nombreux programmeurs penseront que la tâche se bloquera jusqu'à ce qu'il y ait un espace dans la file d'attente du pool de threads. En fait, si l'exécution d'une tâche ne peut pas être planifiée, la méthode submit() de ThreadPoolExecutor lancera une RejectedExecutionException.
38) Quelle est la différence entre les méthodes submit() etexecute() dans le pool de threads Java ?
Les deux méthodes peuvent soumettre des tâches au pool de threads. Le type de retour de la méthode execute() est void, qui est défini dans l'interface Executor, et la méthode submit() peut renvoyer un holding Future. les résultats du calcul. Object, qui est défini dans l'interface ExecutorService, qui étend l'interface Executor. D'autres classes de pool de threads comme ThreadPoolExecutor et ScheduledThreadPoolExecutor ont ces méthodes.
39) Qu'est-ce que la méthode de blocage ?
La méthode de blocage signifie que le programme attendra que la méthode se termine sans rien faire d'autre. La méthode accept() de ServerSocket consiste à attendre que le client se connecte. Le blocage signifie ici qu'avant que le résultat de l'appel ne soit renvoyé, le thread actuel sera suspendu et ne reviendra pas tant que le résultat n'est pas obtenu. De plus, il existe des méthodes asynchrones et non bloquantes qui reviennent avant que la tâche ne soit terminée.
40) Swing est-il thread-safe ? Pourquoi?
Vous pouvez répondre avec certitude que Swing n'est pas thread-safe, mais vous devez expliquer la raison de votre réponse même si l'intervieweur ne vous demande pas pourquoi. Lorsque nous disons que Swing n'est pas thread-safe, nous mentionnons souvent ses composants qui ne peuvent pas être modifiés en multi-threads. Toutes les mises à jour des composants de l'interface graphique doivent être effectuées dans le thread AWT, et Swing propose deux méthodes de rappel : synchrone et asynchrone. .à mettre à jour.
41) Quelle est la différence entre InvoquerAndWait et InvoquerLater en Java ?
Ces deux méthodes sont fournies par l'API Swing aux développeurs Java pour mettre à jour les composants de l'interface graphique à partir du thread actuel au lieu du thread de répartition d'événements. InvokeAndWait() met à jour de manière synchrone les composants de l'interface graphique, tels qu'une barre de progression. Une fois la progression mise à jour, la barre de progression doit également changer en conséquence. Si la progression est suivie par plusieurs threads, appelez la méthode InvocationAndWait() pour demander au thread de répartition d'événements de mettre à jour le composant en conséquence. La méthode InvoqueLater() appelle le composant de mise à jour de manière asynchrone.
42) Quelles méthodes de l'API Swing sont thread-safe ?
Cette question mentionne également la sécurité du swing et des threads. Bien que le composant ne soit pas thread-safe, certaines méthodes peuvent être appelées en toute sécurité par plusieurs threads, telles que repaint(), revalidate(). La méthode setText() de JTextComponent et les méthodes insert() et append() de JTextArea sont également thread-safe.
43) Comment créer un objet Immuable en Java ?
Ce problème semble n'avoir rien à voir avec le multi-threading, mais l'immuabilité peut aider à simplifier des programmes concurrents déjà complexes. Les objets immuables peuvent être partagés sans synchronisation, réduisant ainsi la surcharge de synchronisation pour l'accès simultané à l'objet. Cependant, Java n'a pas l'annotation @Immutable. Pour créer une classe immuable, vous devez implémenter les étapes suivantes : initialiser tous les membres via la méthode constructeur, ne pas fournir de méthodes de définition pour les variables et déclarer tous les membres comme privés, de sorte que direct l'accès n'est pas autorisé.Lors de l'accès à ces membres, dans la méthode getter, ne renvoyez pas directement l'objet lui-même, mais clonez l'objet et renvoyez une copie de l'objet. Mon article sur la façon de rendre un objet immuable en Java contient un didacticiel détaillé. Après l'avoir lu, vous pouvez être sûr.
44) Qu'est-ce que ReadWriteLock en Java ?
De manière générale, les verrous en lecture-écriture sont le résultat de la technologie de séparation des verrous utilisée pour améliorer les performances des programmes concurrents. ReadWriteLock en Java est une nouvelle interface de Java 5. Un ReadWriteLock maintient une paire de verrous associés, un pour les opérations en lecture seule et un pour l'écriture. En l'absence de thread d'écriture, un verrou de lecture peut être détenu par plusieurs threads de lecture en même temps. Les verrous en écriture sont exclusifs. Vous pouvez utiliser ReentrantReadWriteLock dans le JDK pour implémenter cette règle. Il prend en charge jusqu'à 65 535 verrous en écriture et 65 535 verrous en lecture.
45) Qu'est-ce qu'une boucle occupée en multi-threading ?
Une boucle occupée se produit lorsque les programmeurs utilisent une boucle pour faire attendre un thread, contrairement aux méthodes traditionnelles de wait(), sleep() ou rendement() abandonnent tous le contrôle du CPU, et la boucle occupée n'abandonne pas le CPU, elle exécute une boucle vide. Le but est de préserver le cache du CPU. Dans un système multicœur, un thread en attente peut s'exécuter sur un autre cœur à son réveil, ce qui reconstruira le cache. Il peut être utilisé afin d'éviter de reconstruire le cache et de réduire le temps d'attente pour la reconstruction.
46) Quelle est la différence entre les variables volatiles et les variables atomiques ?
C'est une question intéressante. Tout d’abord, les variables volatiles et les variables atomiques se ressemblent, mais leurs fonctions sont différentes. Les variables volatiles peuvent garantir une relation d'anticipation, c'est-à-dire qu'une opération d'écriture se produira avant une opération de lecture ultérieure, mais elles ne garantissent pas l'atomicité. Par exemple, si la variable count est modifiée avec volatile, l'opération count++ n'est pas atomique. La méthode atomique fournie par la classe AtomicInteger peut rendre cette opération atomique. Par exemple, la méthode getAndIncrement() effectuera atomiquement une opération d'incrémentation pour en ajouter un à la valeur actuelle. Des opérations similaires peuvent également être effectuées sur d'autres types de données et variables de référence.
47) Que se passe-t-il si un thread à l'intérieur d'un bloc synchronisé lève une exception ?
Cette question a troublé de nombreux programmeurs Java. Si vous pouvez penser à savoir si le verrou est libéré pour y répondre, vous pouvez espérer y parvenir. Que votre bloc synchronisé se termine normalement ou anormalement, le thread à l'intérieur libérera le verrou, donc par rapport à l'interface de verrouillage, je préfère le bloc synchronisé car il ne me demande pas de dépenser d'énergie pour libérer le verrou. Cette fonction peut être implémentée. en libérant le verrou dans le bloc final.
48) Qu'est-ce que le verrouillage à double contrôle en mode singleton ?
Cette question est souvent posée dans les entretiens Java, mais les enquêteurs ne sont satisfaits qu'à 50 % de la réponse à cette question. La moitié des gens ne peuvent pas écrire une double vérification du verrouillage et la moitié des gens ne peuvent pas expliquer ses dangers cachés ni comment Java 1.5 les corrige. Il s'agit en fait d'une ancienne méthode utilisée pour créer des singletons thread-safe. Lorsque l'instance singleton est créée pour la première fois, elle tente d'utiliser un seul verrou pour optimiser les performances, mais elle échoue dans JDK1.4 car elle est trop complexe. ça ne me plaît pas non plus. Quoi qu'il en soit, même si vous ne l'aimez pas, cela vaut la peine de le savoir car on le demande souvent.
49) Comment créer un Singleton thread-safe en Java ?
Ceci fait suite à la question ci-dessus. Si vous n'aimez pas les verrous revérifiés et que l'intervieweur vous pose des questions sur les méthodes alternatives de création d'une classe Singleton, vous pouvez utiliser le chargement de classe de la JVM. et des fonctionnalités d'initialisation de variables statiques pour créer des instances Singleton, ou en utilisant des types d'énumération pour créer des Singletons, j'aime cette méthode.
50) Écrivez 3 bonnes pratiques multithread que vous suivez
J'aime le plus ce genre de question, je crois que vous écrivez du code simultané pour améliorer les performances Certains meilleurs les pratiques seront également suivies. Voici trois bonnes pratiques que je pense que la plupart des programmeurs Java devraient suivre :
51) Comment forcer le démarrage d'un fil de discussion ?
Cette question est de savoir comment forcer le garbage collection Java. Il n'existe actuellement aucune méthode. Bien que vous puissiez utiliser System.gc() pour effectuer le garbage collection, il n'y a aucune garantie de succès. Il n'existe aucun moyen de forcer le démarrage d'un thread en Java, il est contrôlé par le planificateur de threads et Java ne publie pas l'API correspondante.
52) Qu'est-ce que le framework fork join en Java ?
Le framework fork join est un outil efficace apparu dans le JDK7, grâce auquel les développeurs Java peuvent tirer pleinement parti des multiprocesseurs sur les serveurs modernes. Il est spécialement conçu pour les applications qui peuvent être divisées de manière récursive en plusieurs sous-modules afin d'utiliser toute la puissance de traitement disponible pour améliorer les performances du programme. Un énorme avantage du framework fork join est qu'il utilise un algorithme de vol de travail. Les threads de travail capables d'effectuer davantage de tâches peuvent voler des tâches à d'autres threads pour les exécuter.
53) Quelle est la différence entre appeler les méthodes wait() et sleep() en multi-threading Java ?
L'attente et la mise en veille dans les programmes Java provoqueront une certaine forme de pause et peuvent répondre à différents besoins. La méthode wait() est utilisée pour la communication entre les threads. Si la condition d'attente est vraie et que d'autres threads sont réveillés, elle libérera le verrou, tandis que la méthode sleep() libère uniquement les ressources CPU ou arrête le thread en cours pendant une période de 30 minutes. temps, mais ne libère pas le verrou.
Pour plus de connaissances sur les entretiens liés à Java, veuillez visiter la colonne questions d'entretien Java !
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!