Qu'est-ce qu'une piscine de fil
Un pool de threads est une collection de threads qui [Loop Exécution] Logique d'application multiple dans un ou plusieurs threads.
D'une manière générale, les piscines de fil ont les parties suivantes:
Un ou plusieurs threads qui complètent la tâche principale.
Fil de gestion utilisés pour la gestion de la planification.
La file d'attente de tâche doit être exécutée.
La fonction du pool de threads:
La fonction d'un pool de threads est de limiter le nombre de threads exécutés dans le système.
Selon l'environnement système, le nombre de threads peut être défini automatiquement ou manuellement pour obtenir le meilleur effet de fonctionnement; Moins de ressources système sont gaspillées et plus de congestion du système n'est pas élevée. Utilisez un pool de threads pour contrôler le nombre de threads, et d'autres threads attendent en ligne. Une fois une tâche exécutée, la première tâche est tirée de la file d'attente pour démarrer l'exécution. S'il n'y a pas de processus d'attente dans la file d'attente, cette ressource du pool de threads attend. Lorsqu'une nouvelle tâche doit être exécutée, s'il y a des threads de travail en attente dans le pool de threads, il peut commencer à fonctionner; Sinon, il entrera dans la file d'attente en attente.
Implémentez le pool de threads par vous-même
Sur la base de la compréhension ci-dessus du pool de fils, nous écrivons notre propre pool de fils simple:
Interface de pool de thread simple:
Interface publique Threadpool <Job étend Runnable> {// Exécuter une tâche (travail), ce travail doit implémenter Runnable void execute (travail de travail); // Fermez la fermeture du pool de threads (); // augmente le thread de travail, c'est-à-dire le thread utilisé pour exécuter la tâche void addWorkers (int num); // Réduisez le fil de filetage du travail enlèvement (int num); // Obtenez le nombre de tâches en attente d'être exécutée void getJobSize ();}Le client peut soumettre le travail au pool de threads via la méthode d'exécution (travail) pour l'exécution, et le client n'a pas à attendre l'exécution du travail. En plus de la méthode EXECUTE (JOB), l'interface de pool de threads fournit des méthodes pour augmenter / diminuer les threads des travailleurs et fermer les pools de threads. Chaque client soumet un travail qui saisira une file d'attente de travail et attendra que le fil du travail du travail se traite.
L'implémentation par défaut de l'interface du pool de threads
classe publique defaultThreadpool <Job étend Runnable> implémente Threadpool <Job> {// Nombre maximum de threads pour le travailleur de maintenance du pool de thread Thread Private Static Final int max_worker_numbers = 10; // Valeur par défaut de la maintenance du pool de threads ouvriers du travail de filetage statique final final intrafault_worker_numbers = 5; // Nombre minimum de filetage de maintenance du pool de filetage filetage statique final statique int min_worker_numbers = 1; // Maintenir une liste de travaux, qui ajoute le travail initié par le client privé final linked <whork> jobs = new LinkedList <Job> (); // Liste des threads de travail Liste finale privée <Dorking> Workers = Collection.SynchronizedList (New ArrayList <Dorking> ()); // Nombre de threads de travail privé int workernum; // Générer un threadnum atomiclong privé = new atomiclong (); // Générer du thread pool public public defaultThreadpool () {this.workernum = default_worker_numbers; InitializeWorkers (this.workernum); } public defaultThreadpool (int num) {if (num> max_worker_numbers) {this.workernum = default_worker_numbers; } else {this.workernum = num; } initializeworkers (this.workernum); } // Initialiser chaque filetage de travail privé void initializeworkers (int num) {for (int i = 0; i <num; i ++) {worker worker = new Worker (); // Ajouter à la liste des travailleurs Threads Workers.Add (travailleur); // Démarrer le thread thread thread de travail = nouveau thread (travailleur); thread.start (); }} public void execute (Job Job) {if (job! = null) {// Selon le "mécanisme d'attente / notifier" du thread, nous devons verrouiller les travaux synchronisés (jobs) {jobs.addlast (job); jobs.notify (); }}} // Fermez le pool de threads qui consiste à fermer chaque fil de travail public void shutdown () {for (Worker W: Workers) {w.shutdown (); }}} // Ajouter un thread de travail public void addWorkers (int num) {// Ajouter un verrouillage pour empêcher le thread d'augmenter ou de terminer tandis que le thread suivant continue d'augmenter, ce qui fait dépasser le thread des travailleurs dépasser la valeur maximale synchronisée (jobs) {if (num + this.workernum> max_worker_numbers) {num = max_worker_numbers - this.workernum; } initializeworkers (num); this.workernum + = num; }} // Réduisez le thread de travail public void enlèveworker (int num) {synchronisé (jobs) {if (num> = this.workernum) {throw new illégalargumentException ("dépasser le nombre de threads existants"); } pour (int i = 0; i <num; i ++) {wearch worker = workers.get (i); if (worker! = null) {// Fermez le thread et supprimez worker.shutdown (); travailleurs.remove (i); }} this.workernum - = num; }} public int getJobSize () {// TODO Méthode générée automatique Stume de retour workers.size (); } // Définir la classe de thread de travail implémente Runnable {// indique si le travailleur privé volatile booléen running = true; public void run () {while (running) {job job = null; ! retour; }} // supprimer un travail de travail = jobs.RemoveFirst (); } // Exécuter Job if (Job! = Null) {job.run (); }}} // terminer le thread public void shutdown () {running = false; }}}
D'après la mise en œuvre du pool de threads, on peut voir que lorsque le client appelle la méthode EXECUTE (JOB), il ajoutera constamment des emplois aux travaux de liste de tâches, et chaque fil de travail ne lira pas les travaux des travaux à exécuter. Lorsque les emplois sont vides, le fil du travailleur entre dans l'état d'attente.
Après avoir ajouté un emploi, la méthode Notify () est appelée sur les travaux de file d'attente de travail pour réveiller un fil de travail. Ici, nous n'appelons pas notifyall () pour éviter de gaspiller les ressources en déplaçant tous les threads dans la file d'attente d'attente dans la file d'attente de blocage.
L'essence d'un pool de threads consiste à utiliser une file d'attente de travail pour connecter les threads et les threads du client. Le fil du client revient après avoir mis la tâche dans la file d'attente de travail, tandis que le thread de travailleur prend mal le travail de la file d'attente de travail et l'exécute. Lorsque la file d'attente de travail est vide, le fil du travailleur entre dans l'état d'attente. Lorsqu'un client envoie une tâche, il passera par tout fil de travail. Avec la soumission d'un grand nombre de tâches, plus de fils de travailleur sont éveillés.
Référence: "L'art de la programmation simultanée en Java" Fang Tengfei