java asynchrone - thread, pool de threads

1. 4 façons d'initialiser les threads en Java

  1. Hériter du thread, réécrire la méthode d'exécution
  2. Implémenter l'interface Runnable
  3. Implémenter l'interface Callable + FutureTask (peut obtenir l'interface de retour de thread, peut gérer les exceptions)
  4. Pool de fils

  • Dans tous les cas, vous devez utiliser new Thread pour ouvrir le fil

2. 4 cas de réalisation

2.1. Hériter de la méthode Thread

3. Implémenter l'interface Runnable

2.2. Implémenter l'interface Callable

  • Implémenter l'interface Callable et spécifier le type générique
  • Remplacer la méthode d'appel
  • Lors de l'utilisation, passez l'objet de classe d'implémentation appelable lors de la nouvelle FutureTask
  • Étant donné que la couche inférieure de FutureTask utilise l'interface exécutable, le nouvel objet Thread peut être passé dans l'objet FutureTask

Lorsque l'objet FutureTask doit obtenir les données renvoyées du thread :

  • Obtenir des résultats en bloquant les threads et en attendant : contrairement à l'intention initiale du multi-threading

2.3, pool de threads

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author 线程池使用
 * @date 2023/7/7
 */
public class ExecutorsPool {
    /**
     * 在java JUC下,提供了一个类Executors,快速创建一个线程池
     *   下面创建一个固定数据为10的线程池
     */
    public static ExecutorService executors = Executors.newFixedThreadPool(10);

    //测试案例
    public static void main(String[] args) {
        System.out.println("主方法..................开始执行");
        
        //executors.submit(new Runnable() {
        //    @Override
        //    public void run() {
        //        
        //    }
        //})
        /** 下面是上面的lambda写法 */
        executors.submit(() -> {
            System.out.println("当前线程编号为:" + Thread.currentThread().getContextClassLoader());
            int a = 10 / 5;
            System.out.println("线程计算结果为:" + a);
        });
        System.out.println("主方法..................结束执行");
    }
}

Le résultat est le suivant :

Avis:

Executors.submit() et Executors.execute() par exemple :

  • Le type de retour de la méthode submit est Future<T>, et le résultat du thread peut être obtenu
  • Le type de retour de la méthode d'exécution est void et le résultat du thread ne peut pas être obtenu

3. Pool de threads

3.1, la méthode de création originale

  • ThreadPoolExecutor exécuteur = new ThreadPoolExecutor();
  • Passez simplement les sept paramètres du thread
  • La couche inférieure de ThreadPoolExecutor et Executors dans 2.4 implémente ExecutorService

3.2. Sept paramètres de threads

<1> corePoolSize

Nombre de threads principaux :

  • Une fois le pool de threads créé, il existera jusqu'à ce que le pool de threads soit détruit.
  • Une fois le pool de threads créé, le nombre de threads prêts, attendant de recevoir des tâches asynchrones à exécuter

Par exemple : corePoolSize = 5 Après la création du thread, il y a 5 threads dans le pool de threads Thread pour traiter les affaires à tout moment start()

<2>taille maximale du pool

Nombre maximal de threads :

  • Nombre maximal de threads, utilisés pour contrôler les ressources
<3>heepAliverTime

Temps de survie :

  • Le nombre de threads actuels est supérieur au nombre de threads principaux, et lorsque les threads inactifs dépassent le temps de survie , libère les threads inactifs redondants
  • Le thread inactif fait ici référence à : l'activité de thread a été traitée et attend une nouvelle activité multi-thread. À ce stade, le thread est inactif.
  • Threads libérés : étant donné qu'il existe des threads principaux, les threads inactifs libérés sont : le nombre de threads actuels - le nombre de threads principaux
<4>Unité d'unité de temps

unité de durée de vie

<5>BlockingQueue<Runnable> workQueue

Blocage de la file d'attente :

  • S'il y a beaucoup de tâches multi-thread, les tâches redondantes actuelles seront placées dans la file d'attente
  • Tant qu'un thread est inactif, une nouvelle tâche sera extraite de la file d'attente pour exécution
<6>threadFactory

usine de création de fils

<7>Gestionnaire RejectedExecutionHandler

Processeur : si la file d'attente est pleine, refuser d'exécuter la tâche selon la politique de rejet que nous avons spécifiée (politique de saturation)

3.3 Cas

 Ordre de travail du pool de threads
  1. Une fois le pool de threads créé, le nombre de threads principaux est prêt à recevoir des tâches multithreads
  2. Lorsque le thread principal est plein, il place les tâches entrantes dans la file d'attente de blocage, et le noyau inactif ira dans la file d'attente de blocage pour obtenir l'exécution de la tâche par lui-même.
  3. Lorsque la file d'attente de blocage est pleine, un nouveau thread est ouvert directement pour exécuter la tâche, et le maximum ne peut être ouvert qu'au nombre spécifié par max
  4. Lorsque max est plein, utilisez la stratégie de rejet du gestionnaire pour rejeter la tâche
  5. Une fois l'exécution de max terminée, s'il y a de nombreux threads inactifs, après le temps spécifié keepAliveTime, libère les threads redondants
cas d'entretien
  • Comment un thread core 7 ; max 20 ; file d'attente 50 ; 100 est-il alloué simultanément ?
  1. 7 la concurrence sera exécutée immédiatement
  2. 50 entreront dans la file d'attente
  3. Ouvrez-en 13 de plus pour exécution, en voici 13 dans la file d'attente ! (FIFO et LIFO, dépend principalement de la file d'attente utilisée)
  4. Utilisez la stratégie de rejet pour les 30 autres, par exemple : utilisez la stratégie de rejet CallerRunsPolicy pour autoriser l' exécution synchrone simultanée restante

comme:

import java.util.concurrent.*;

public class ThreadPoolTest {
    public static void main(String[] args) {
        System.out.println("线程池创建......");
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                7
                , 20
                , 10
                , TimeUnit.SECONDS
                , new LinkedBlockingDeque<>(50)
                , Executors.defaultThreadFactory()
                , new ThreadPoolExecutor.AbortPolicy()
        );
        //模拟100个并发
        for (int i = 0; i < 100; i++) {
            int num = i;
            executor.execute(()->{
                System.out.println(Thread.currentThread().getName() + "is executing:" + num);
                try {
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}

résultat:

线程池创建......
pool-1-thread-1est en cours d'exécution:0
pool-1-thread-5est en cours d'exécution:4
pool-1-thread-7est en cours d'exécution:6
pool-1-thread-6est en cours d'exécution:5
pool -1-thread-3est en cours d'exécution:2
pool-1-thread-2est en cours d'exécution:1
pool-1-thread-4est en cours d'exécution:3
pool-1-thread-8est en cours d'exécution:57
pool-1-thread-9est en cours d'exécution:58
pool -1-thread-11est en cours d'
exécution:60 pool-1-thread-10est en cours d'
exécution:59 pool-1-thread-13est en cours d'exécution:62
pool-1-thread-12est en cours d'exécution:61
pool-1-thread-14est en cours d'exécution:63
pool -1-thread-17est en cours d'exécution:66
pool-1-thread-15est en cours d'exécution:64
pool-1-thread-16est en cours d'exécution:65
pool-1-thread-19est en cours d'exécution:68
pool-1-thread-18est en cours d'exécution:67
pool-1-thread-20est en cours d'exécution:69
Exception dans le thread "principal" @357246de rejeté de java.util.concurrent.ThreadPoolExecutor@2a18f23c[En cours d'exécution, taille du pool = 20, threads actifs = 20, tâches en file d'attente = 50, tâches terminées = 0]
    sur java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor .java:2047)
    sur java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
    sur java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
    sur com.shuizhu.helloworld.thread.ThreadPoolTest. main(ThreadPoolTest.java:20)
pool-1-thread-1est en cours d'exécution:7
pool-1-thread-16est en cours d'exécution:10
pool-1-thread-4est en cours d'exécution:11
pool-1-thread-14est en cours d'exécution:9
pool-1-thread-13est en cours d'exécution:8
pool-1-thread-19est en cours d'exécution:13
pool-1-thread-5est en cours d'exécution:12
pool-1-thread-15est en cours d'
exécution:15 pool-1-thread-10est en cours d'exécution:17
pool-1-thread-8est en cours d'exécution:19
pool-1-thread-2est en cours d'exécution:22
pool-1-thread-17est en cours d'exécution:14
pool-1-thread
-18est en cours d'exécution:25 pool-1-thread-20est en cours d'exécution:26
pool-1-thread-9est en cours d'exécution:24
pool-1-thread-7est en cours d'exécution:20
pool-1-thread-11est en cours d'exécution:23
pool-1-thread-6est en cours d'exécution:21
pool-1-thread-3est en cours d'exécution:18
pool-1-thread-12est en cours d'exécution:16
pool-1-thread-1est en cours d'exécution:27
pool-1-thread-14est en cours d'
exécution:31 pool-1-thread-4est en cours d'exécution:30
pool-1-thread-16est en cours d'exécution:29
pool-1-thread-13est en cours d'exécution:28
pool-1-thread-20est en cours d'exécution:32
pool-1-thread
-18est en cours d'exécution:37 pool-1-thread-17est en cours d'exécution:40
pool-1-thread-8est en cours d'exécution:36
pool-1-thread-15est en cours d'exécution:35
pool-1-thread-19est en cours d'exécution:33
pool-1-thread-5est en cours d'
exécution:34 pool-1-thread-2est en cours d'exécution:39
pool-1-thread-10est en cours d'exécution:38
pool-1-thread-3est en cours d'exécution:41
pool-1-thread-11est en cours d'exécution:43
pool-1-thread-6est en cours d'exécution:42
pool-1-thread-9est en cours d'exécution:46
pool-1-thread-12est en cours d'exécution:44
pool-1-thread-7 est en cours d'exécution : 45 

politique de rejet
  • DiscardOldestPolicy

Supprimer les anciennes tâches qui n'ont pas encore été exécutées (le début de la file d'attente est la plus ancienne) et exécuter de nouvelles tâches

  • CallerRunsPolicyCallerRunsPolicy

Les threads redondants s'exécutent et appellent directement la méthode run, qui équivaut à une exécution synchrone

  • AbortPolicy (la politique de rejet par défaut)

La nouvelle tâche est rejetée directement et une exception sera levée

  • DiscardPolicy

La nouvelle tâche est supprimée directement sans lever d'exception

3.4, Les exécuteurs créent un pool de threads

La création du pool de threads ci-dessus est la méthode native

Vous pouvez également utiliser des exécuteurs pour créer des pools de threads

1、Executors.newCachedThreadPool();
  • core core thread est 0, le nombre maximum de threads est Integer.MAX_VALUE
  • Créez un pool de threads qui peut mettre en cache les threads (puisque le thread principal est 0, le temps de cache est de 60 secondes), qui peut recycler de manière flexible les threads inactifs

2、Executors.newFixedThreadPool(10);
  • Créer un pool de threads avec un nombre fixe de threads
  • Core thread = thread maximum, donc le thread est toujours actif
  • Vous pouvez contrôler le nombre maximum de threads simultanés, et les threads excédentaires attendront dans la file d'attente

3、Executors.newScheduledThreadPool(10);
  • Créer un pool de threads de longueur fixe pour prendre en charge la synchronisation et l'exécution périodique des tâches
  • Vous pouvez spécifier le temps d'exécution après

4、Executors.newSingleThreadExecutor();
  •  Créez un pool de threads à thread unique qui utilise uniquement un thread de travail unique pour exécuter des tâches afin de garantir que toutes les tâches sont exécutées
  • Scénario applicable : dans l'environnement distribué, pour assurer la cohérence de la double écriture, la même entreprise doit être laissée au même serveur ou au même thread pour le traitement

Je suppose que tu aimes

Origine blog.csdn.net/weixin_42675423/article/details/131564775
conseillé
Classement