Cet article vous aide à maîtriser les connaissances de base du multithreading Java pour correspondre aux problèmes que vous rencontrez à l'avenir. Le contenu spécifique est le suivant
1. Questions d'interview multithreads Java
1. Quelle est la différence entre un processus et un fil?
Un processus est un environnement de fonctionnement autonome, qui peut être considéré comme un programme ou une application. Un thread est une tâche exécutée dans un processus. L'environnement Java Runtime est un processus unique qui contient différentes classes et programmes. Les threads peuvent être appelés processus légers. Les threads nécessitent moins de ressources pour créer et résider dans le processus et peuvent partager des ressources dans le processus.
2. Quels sont les avantages de la programmation multi-thread?
Dans un programme multi-thread, plusieurs threads sont exécutés simultanément pour améliorer l'efficacité du programme, et le processeur n'entrera pas un état d'inactivité car un certain thread doit attendre les ressources. Plusieurs threads partagent la mémoire du tas, donc créer plusieurs threads pour effectuer certaines tâches est mieux que de créer plusieurs processus. Par exemple, les servlets sont meilleurs que CGI car les servlets prennent en charge le multithreading, alors que CGI ne le fait pas.
3. Quelle est la différence entre les threads utilisateur et les fils de démon?
Lorsque nous créons un thread dans un programme Java, il est appelé un thread utilisateur. Un thread de démon est un fil qui s'exécute en arrière-plan et ne bloque pas le JVM terminé. Lorsqu'aucun thread utilisateur n'est en cours d'exécution, le JVM ferme le programme et sort. Le fil d'enfant créé par un fil de démon est toujours un fil de démon.
4. Comment créons-nous un fil?
Il existe deux façons de créer des threads: l'un consiste à implémenter l'interface Runnable, puis à le passer au constructeur de thread et à créer un objet de thread; L'autre consiste à hériter directement de la classe de threads. Pour plus d'informations, vous pouvez lire cet article sur la façon de créer des threads en Java.
5. Quels sont les différents cycles de vie du fil?
Lorsque nous créons un nouveau fil dans un programme Java, son statut est nouveau. Lorsque nous appelons la méthode start () du thread, l'état est changé en fonctionnement. Le planificateur de threads alloue le temps CPU aux threads dans le pool de threads Runnable et change leur état en fonctionnement. D'autres états de fil comprennent l'attente, bloquée et morte. Lisez cet article pour en savoir plus sur les cycles de vie de fil.
6. Puis-je appeler directement la méthode run () de la classe de threads?
Bien sûr, mais si nous appelons la méthode Run () de Thread (), cela se comportera de la même manière que la méthode normale. Afin d'exécuter notre code dans un nouveau thread, la méthode thread.start () doit être utilisée.
7. Comment faire une pause d'un fil en cours d'exécution pendant une période de temps?
Nous pouvons utiliser la méthode Sleep () de la classe de threads pour suspendre le fil pendant une période de temps. Il convient de noter que cela ne fait pas terminer le fil. Une fois le fil éveillé de l'hibernation, l'état du thread sera changé en exécutable, et en fonction de la planification du thread, il sera exécuté.
8. Quelle est votre compréhension de la priorité du fil?
Chaque fil a une priorité. D'une manière générale, les threads de grande priorité auront la priorité lors de l'exécution, mais cela dépend de l'implémentation de la planification du thread, qui est lié au système d'exploitation (OS dépendant). Nous pouvons définir la priorité des threads, mais cela ne garantit pas que les threads de haute priorité s'exécuteront devant des threads à faible priorité. La priorité du thread est une variable int (de 1 à 10), 1 représente la priorité la plus faible et 10 représente la priorité la plus élevée.
9. Que sont les planificateurs de fil et le découpage du temps?
Un planificateur de threads est un service de système d'exploitation qui est responsable de l'allocation du temps CPU aux threads à l'état Runnable. Une fois que nous avons créé un thread et le démarrer, son exécution dépend de l'implémentation du planificateur de threads. Le temps en temps révèle au processus d'allocation du temps de processeur disponible aux threads coulissables disponibles. Le temps de CPU alloué peut être basé sur la priorité du thread ou le temps d'attente du fil. La planification du thread n'est pas contrôlée par les machines virtuelles Java, il est donc préférable de le contrôler par l'application (c'est-à-dire ne laissez pas votre programme dépendre des priorités du thread).
10. Dans Multithreading, qu'est-ce que le changement de contexte?
La commutation de contexte est un processus de stockage et de restauration de l'état du processeur, ce qui permet à l'exécution du thread de reprendre l'exécution des points d'interruption. La commutation contextuelle est une caractéristique de base des systèmes d'exploitation multi-tâches et des environnements multi-thread.
11. Comment vous assurez-vous que le fil où se trouve la méthode principale () est le dernier fil qui se termine dans le programme Java?
Nous pouvons utiliser la méthode joint () de la classe de threads pour nous assurer que tous les threads créés par le programme se terminent avant que la méthode principale () ne sorte. Voici un article sur la méthode conjointe () de la classe de threads.
12. Comment les fils communiquent-ils?
Lorsque les ressources inter-thread peuvent être partagées, la communication inter-thread est un moyen important de les coordonner. La méthode wait () / notify () / notifyall () dans la classe d'objets peut être utilisée pour communiquer entre les threads sur l'état des verrous sur les ressources. Cliquez ici pour en savoir plus sur l'attente du fil, notifier et notifier.
13. Pourquoi les méthodes de communication du thread Wait (), Notify () et Notifyall () sont-elles définies dans la classe d'objets?
Chaque objet de Java a une serrure (moniteur, qui peut également être un moniteur) et attendre (), notifier () et d'autres méthodes sont utilisées pour attendre le verrouillage de l'objet ou aviser d'autres objets de threads. Il n'y a pas de verrous et de synchroniseurs disponibles pour tout objet à utiliser dans les threads Java. C'est pourquoi ces méthodes font partie de la classe d'objets, afin que chaque classe de Java ait des méthodes de base pour la communication inter-thread
14. Pourquoi attendre (), notifier () et notifyall () dans une méthode de synchronisation ou un bloc de synchronisation?
Lorsqu'un thread doit appeler la méthode Wait () de l'objet, le thread doit avoir le verrou de l'objet. Ensuite, il libère le verrouillage de l'objet et entre dans l'état d'attente jusqu'à ce que d'autres threads appellent la méthode notify () sur l'objet. De même, lorsqu'un thread doit appeler la méthode Notify () de l'objet, il libérera le verrou de l'objet afin que les autres threads attendent d'obtenir le verrou de l'objet. Étant donné que toutes ces méthodes nécessitent des threads pour maintenir le verrou de l'objet, ils ne peuvent être implémentés que par synchronisation, ils ne peuvent donc être appelés que dans la méthode de synchronisation ou le bloc de synchronisation.
15. Pourquoi les méthodes de sommeil () et de rendement () de la classe de threads sont-elles statiques?
Les méthodes sleep () et rendu () de la classe de thread s'exécuteront sur le thread en cours d'exécution. Il n'est donc pas logique d'appeler ces méthodes sur d'autres fils qui sont dans un état d'attente. C'est pourquoi ces méthodes sont statiques. Ils peuvent travailler dans le fil actuellement exécuté et éviter la croyance erronée du programmeur que ces méthodes peuvent être appelées dans d'autres threads non coupés.
16. Comment assurer la sécurité des filetages?
Il existe de nombreuses façons d'assurer la sécurité des threads en Java - Synchronisation, d'utiliser des classes simultanées atomiques, d'implémenter des verrous simultanés, d'utiliser des mots clés volatils, d'utiliser des classes invariantes et des classes de filetage. Vous pouvez en savoir plus dans le didacticiel de la sécurité du fil.
17. Quel est le rôle du mot-clé volatil dans Java?
Lorsque nous utilisons le mot clé volatil pour modifier une variable, le thread lira directement la variable et ne le mettra pas en cache. Cela garantit que les variables lues par le thread sont cohérentes en mémoire.
18. Quel est le meilleur choix, la méthode de synchronisation ou le bloc de synchronisation?
Les blocs synchrones sont un meilleur choix car il ne verrouille pas l'ensemble de l'objet (et bien sûr, vous pouvez également le laisser verrouiller l'ensemble de l'objet). La méthode de synchronisation verrouille l'ensemble de l'objet, même s'il existe plusieurs blocs de synchronisation non liés dans la classe, ce qui les fait généralement arrêter l'exécution et doit attendre pour obtenir le verrou sur l'objet.
19. Comment créer un fil de démon?
Utilisez la méthode setDaemon (True) de la classe de threads sur la méthode SetDaemon (True) pour définir le thread en tant que thread démon. Il convient de noter que cette méthode doit être appelée avant d'appeler la méthode START (), sinon un IllégalThreadStateException sera lancé.
20. Qu'est-ce que Threadlocal?
ThreadLocal est utilisé pour créer des variables locales pour les threads. Nous savons que tous les threads d'un objet partageront ses variables globales, de sorte que ces variables ne sont pas en filetage et nous pouvons utiliser des techniques de synchronisation. Mais lorsque nous ne voulons pas utiliser la synchronisation, nous pouvons choisir la variable threadlocal.
Chaque thread aura ses propres variables de thread, qui peuvent utiliser la méthode get () / set () pour obtenir leurs valeurs par défaut ou modifier leurs valeurs en interne. Les instances threadLocales veulent généralement qu'elles soient associées à l'état de thread en tant qu'attributs statiques privés. Dans cet article, vous pouvez voir un petit programme sur le threadlocal.
21. Qu'est-ce que le groupe de threads? Pourquoi n'est-il pas recommandé?
ThreadGroup est une classe dont le but est de fournir des informations sur les groupes de threads.
L'API ThreadGroup est relativement faible et n'offre pas plus de fonctionnalités que le thread. Il a deux fonctions principales: l'une consiste à obtenir une liste de threads actifs dans le groupe de threads; L'autre consiste à définir un gestionnaire d'exceptions non appris pour les fils. Cependant, dans Java 1.5, la classe de thread a également ajouté la méthode SetUncaughtexceptionHandler (ungaughtexceptionHandler eh), de sorte que le groupe Thread est dépassé et il n'est pas recommandé de continuer à l'utiliser.
t1.SetUncaughtexceptionHandler (new ungaughtexceptionHandler () {@Override public void ungaughtexception (thread t, lanceable e) {System.out.println ("Exception s'est produite:" + e.getMessage ());}}); 22. Qu'est-ce qu'un vidage de fil Java et comment l'obtenir?
Le vidage du thread est une liste de threads actifs JVM qui sont très utiles pour analyser les goulots d'étranglement du système et les impasses. Il existe de nombreuses façons d'obtenir des vidages de threads - en utilisant le profileur, la commande kill -3, l'outil JStack, etc. Je préfère l'outil JSTACK car il est facile à utiliser et est livré avec JDK. Puisqu'il s'agit d'un outil basé sur un terminal, nous pouvons écrire certains scripts pour générer des vidages en temps opportun pour l'analyse. Lisez ce document pour en savoir plus sur la génération de vidages de fil.
23. Qu'est-ce qu'une impasse? Comment analyser et éviter les blocages?
L'impasse fait référence à la situation où plus de deux threads sont bloqués pour toujours. Cette situation nécessite au moins deux threads et plus de deux ressources.
Pour analyser les impasses, nous devons afficher le vidage de thread de l'application Java. Nous devons découvrir ces fils avec un état bloqué et les ressources qu'ils attendent. Chaque ressource a un ID unique. En utilisant cet ID, nous pouvons savoir quels threads ont déjà son verrouillage d'objet.
Éviter les serrures imbriquées, utiliser uniquement des verrous là où ils sont nécessaires et éviter une attente indéfinie sont les moyens habituels d'éviter les impasses, lisez cet article pour apprendre à analyser les impasses.
24. Quelle est la classe Java Timer? Comment créer une tâche avec un intervalle de temps spécifique?
Java.util.timer est une classe d'outils qui peut être utilisée pour planifier un fil à exécuter à un certain moment à l'avenir. La classe de minuterie peut être organisée en planifiant des tâches uniques ou des tâches périodiques.
Java.util.Timertask est une classe abstraite qui implémente l'interface Runnable. Nous devons hériter de cette classe pour créer nos propres tâches chronométrées et utiliser la minuterie pour organiser son exécution.
25. Qu'est-ce qu'une piscine de fil? Comment créer une piscine de fil Java?
Un pool de threads gère un ensemble de threads de travail, et il comprend également une file d'attente pour placer des tâches en attente d'être exécutées.
java.util.concurrent.execcutors fournit une implémentation de l'interface java.util.concurrent.executor pour la création de pools de threads. L'exemple de pool de threads montre comment créer et utiliser un pool de threads ou lire l'exemple ScheduledThreadPoolExecutor pour savoir comment créer une tâche périodique.
2. Questions d'interview simultanées Java
1. Qu'est-ce que le fonctionnement atomique? Quelles classes atomiques y a-t-il dans l'API de concurrence Java?
L'opération atomique fait référence à une unité de tâche d'opération qui n'est pas affectée par d'autres opérations. Les opérations atomiques sont des moyens nécessaires pour éviter l'incohérence des données dans un environnement multithread.
Int ++ n'est pas une opération atomique, donc lorsqu'un thread lit sa valeur et ajoute 1, un autre thread peut lire la valeur précédente, ce qui augmentera une erreur.
Pour résoudre ce problème, il est nécessaire de s'assurer que l'opération d'addition est atomique, et nous pourrions utiliser la technologie de synchronisation pour ce faire avant JDK1.5. Pour JDK1.5, le package java.util.concurrent.atomic fournit des types de classes INT et longs de chargement, qui peuvent automatiquement s'assurer qu'ils sont atomiques pour leurs opérations et ne nécessitent pas de synchronisation.
2. Quelle est l'interface de verrouillage dans l'API de concurrence Java? Quels sont les avantages de la comparaison de la synchronisation?
L'interface de verrouillage fournit un fonctionnement plus évolutif de verrouillage que la méthode de synchronisation et le bloc de synchronisation. Ils permettent des structures plus flexibles, peuvent avoir des propriétés complètement différentes et peuvent prendre en charge les objets conditionnels de plusieurs classes connexes.
Ses avantages sont:
Il peut rendre la serrure plus équitable, afin que le fil réagisse aux interruptions en attendant le verrou, afin que le fil puisse essayer d'acquérir le verrou, et revenir immédiatement lorsqu'il ne peut pas acquérir le verrou ou attendre une période de temps, qui peut être acquise et libérée dans différents ordres dans différentes gammes.
3. Quel est le cadre des exécuteurs?
Le cadre exécuteur est introduit dans Java 5 avec l'interface java.util.concurrent.execUtor. Le cadre exécuteur est un cadre qui exécute des tâches asynchrones qui exécutent des appels de stratégie, des planifications, des exécutions et des contrôles en fonction d'un ensemble de politiques.
Les threads de création illimités peuvent provoquer un débordement de mémoire d'application. La création d'un pool de threads est donc une meilleure solution car le nombre de threads peut être limité et le nombre de threads peut être recyclé et réutilisé. L'utilisation du framework des exécuteurs peut facilement créer un pool de threads. Lisez cet article pour apprendre à utiliser l'exécuteur pour créer un pool de threads.
4. Qu'est-ce qu'une file d'attente de blocage? Comment implémenter un modèle producteur-consommateur en utilisant des files d'attente de blocage?
La caractéristique de java.util.concurrent.blockingqueue est: lorsque la file d'attente est vide, le fonctionnement de l'obtention ou de la suppression d'éléments de la file d'attente sera bloqué, ou lorsque la file d'attente est pleine, le fonctionnement des éléments d'ajout à la file d'attente sera bloqué.
La file d'attente de blocage n'accepte pas les valeurs nuls, et lorsque vous essayez d'ajouter des valeurs nulles à la file d'attente, il lance une nulpointerException.
La mise en œuvre des files d'attente de blocage est en filetage, et toutes les méthodes de requête sont atomiques et utilisent des verrous internes ou d'autres formes de contrôle simultané.
L'interface BlockingQueue fait partie du cadre des collections Java, qui est principalement utilisée pour mettre en œuvre des problèmes de consommation de producteur.
5. Que sont appelés et futurs?
Java 5 présente l'interface java.util.concurrent. Il est très similaire à l'interface Runnable, mais il peut renvoyer un objet ou lancer une exception.
L'interface appelable utilise des génériques pour définir son type de retour. La classe des exécuteurs fournit des méthodes utiles pour exécuter des tâches dans un pool de threads. Étant donné que la tâche appelable est parallèle, nous devons attendre le résultat qu'il revient. L'objet java.util.concurrent.future résout ce problème pour nous. Une fois que le pool de thread a soumis la tâche appelée, un futur objet est renvoyé. En utilisant, nous pouvons connaître l'état de la tâche appelée et obtenir le résultat d'exécution renvoyé par le callable. Future fournit une méthode get () qui nous permet d'attendre que le callable se termine et d'obtenir son résultat d'exécution.
6. Qu'est-ce que Futuretask?
FutureTask est une implémentation de base de l'avenir, nous pouvons l'utiliser avec des exécuteurs pour gérer les tâches asynchrones. Habituellement, nous n'avons pas besoin d'utiliser la classe FutureTask, cela devient très utile au moment où nous prévoyons de réécrire certaines méthodes de l'interface future et de conserver l'implémentation de base d'origine. Nous pouvons simplement en hériter et réécrire les méthodes dont nous avons besoin.
7. Quelle est la mise en œuvre de conteneurs simultanés?
Les classes de collecte Java échouent rapidement, ce qui signifie que lorsque l'ensemble est modifié et qu'un thread utilise l'itérateur pour traverser l'ensemble, la méthode Next () de l'Iterator lancera une exception de laModification ConcurrentModification.
Les conteneurs simultanés prennent en charge les mises à jour simultanées et simultanées simultanées.
Les classes principales sont concurrenthashmap, copyOnwriteArrayList et copyOnwriteArraySet. Lisez cet article pour apprendre à éviter la conception de laModification Concurrent.
8. Quelle est la classe des exécuteurs?
Les exécuteurs fournissent quelques méthodes d'outillage pour l'exécuteur, les classes ExecutorService, ScheduleDexeCutOrService, ThreadFactory et Callable.
Les exécuteurs peuvent être utilisés pour créer des pools de threads.
En fait, il existe de nombreuses questions d'entrevue Java plus basiques, et vous pouvez les organiser systématiquement.
J'espère que tout le monde réussira dans l'interview!