JAVA implémente quatre méthodes de multi-threading et ThreadPoolExecutor contenu du pool de threads Explication détaillée de sept paramètres stratégie de rejet pool de threads personnalisé

Analyse détaillée du pool de threads de quatre manières de multithreading JAVA

Multithreading JAVA quatre façons

4 façons d'implémenter des threads en java:

  • 1. Héritez de la classe Thread et remplacez la méthode d'exécution
  • 2. Implémentez l'interface Runnable et implémentez la méthode run
  • 3. Hériter de l'interface Callable pour implémenter la méthode d'appel et utiliser futureTask pour appeler (avec valeur de retour / peut gérer les exceptions)

[Les trois types ci-dessus ne sont pas utilisés dans les codes commerciaux normaux.]

[Toutes les tâches asynchrones multithreads doivent être transférées au pool de threads pour exécution]

  • 4. Pool de threads (réutilisation des threads; contrôle du nombre maximum de threads simultanés; gestion des threads)

    • Réduisez la consommation de ressources

      • Réduisez la perte causée par la création et la destruction de threads en réutilisant les threads déjà créés
    • Améliorez la vitesse de réponse

      • Étant donné que le nombre de threads dans le pool de threads ne dépasse pas la limite maximale, certains threads sont dans un état d'attente pour l'attribution de tâches et, lorsque des tâches arrivent, elles peuvent être exécutées sans créer de nouveaux threads.
    • Améliorez la gestion des threads

      • Le pool de threads optimisera les threads du pool en fonction des caractéristiques du système actuel afin de réduire la surcharge système causée par la création et la destruction de threads. La création et la destruction sans fil de threads réduisent non seulement les ressources système, mais réduisent également la stabilité du système et utilisent le pool de threads pour l'uniformité Distribution

1. Héritez de la classe Thread et remplacez la méthode d'exécution

public class ThreadTest {
    
    
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
//        1.继承Thread类 重写run方法
        new Thread01().start();
        System.out.println("main end ....");
    }
    public static class Thread01 extends  Thread{
    
    
        @Override
        public void run() {
    
    
            System.out.println("1.继承Thread类 重写run方法");
        }
    }
}

2. Implémentez l'interface Runnable et implémentez la méthode run

public class ThreadTest {
    
    
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
//         2.实现Runnable接口 实现run方法
        new Thread(new Runnable01()).start();
        System.out.println("main end ....");
    }
    public static class Runnable01 implements  Runnable{
    
    
        @Override
        public void run() {
    
    
            System.out.println("2.实现Runnable接口 实现run方法");
        }
    }
}

3. Hériter de l'interface Callable pour implémenter la méthode d'appel et utiliser futureTask pour appeler (avec valeur de retour / peut gérer les exceptions)

public class ThreadTest {
    
    
    public  static void main(String args[]) throws ExecutionException, InterruptedException {
    
    
        System.out.println("main start ....");
//        3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)
        Callable01 callable01 = new Callable01();
        FutureTask<Integer> futureTask = new FutureTask<>(callable01);
        new Thread(futureTask).start();
        //使用futureTask 获取返回值  会阻塞等待
        System.out.println(futureTask.get());
        System.out.println("main end ....");
    }
    public static class Callable01 implements Callable<Integer>{
    
    

        @Override
        public Integer call() throws Exception {
    
    
            System.out.println("3.继承Callable接口 实现call方法 使用futureTask调用  (有返回值/可处理异常)");
            return new Integer(200);
        }
    }
}

4. Pool de threads

4.1 Application du pool de threads de base

public class ThreadTest {
    
    
    //正常情况保证一个项目中只有少数线程池,每个异步任务,线程池让他自己取执行
    //Executors.newFixedThreadPool(10); 使用工具类生成容量为10的线程池
    //自定义线程池使用  new ThreadPoolExecutor();  自定义七大参数
    public static ExecutorService service = Executors.newFixedThreadPool(10);
    public  static void main(String args[]){
    
    
        System.out.println("main start ....");
        try{
    
    
            service.execute(()->{
    
    
                System.out.println("4.线程池");
            });
        }catch (Exception e){
    
    
                e.printStackTrace();
        }finally{
    
    
            service.shutdown();
        }
        System.out.println("main end ....");
    }

}

4.2 Outils auxiliaires des exécuteurs

Executors.newFixedThreadPool(int);  //创建固定容量的线程池
Executors.newSingleThreadExecutor();  //创建一个只有1个工作线程的线程池
Executors.newCachedThreadPool() //创建一个可扩容的线程池。执行很多短期异步任务,线程池根据需要创建新线程,但在先前构造的线程可用时将重用他们。可扩容。
public class MyThreadPoolDemo {
    
    
    public  static void main(String args[]){
    
    
        //固定容量的线程池
//        ExecutorService threadPool =Executors.newFixedThreadPool(5); //创建一个有5个工作线程的线程池
//        ExecutorService threadPool =Executors.newSingleThreadExecutor(); //创建一个只有1个工作线程的线程池
        ExecutorService threadPool =Executors.newCachedThreadPool();  //创建一个可扩容的线程池
        try{
    
    
            for (int i = 1; i <10; i++) {
    
    
                //从线程池中使用一个工作线程
                threadPool.execute(()->{
    
    
                    System.out.println(Thread.currentThread().getName());
                });
            }
        }catch (Exception e){
    
    

        }finally{
    
    
            //任务结束 归还线程
            threadPool.shutdown();
        }
    }
}

Les couches inférieures des trois API Executors ci - dessus sont implémentées à l'aide de ThreadPoolExecutor avec différents paramètres.
Insérez la description de l'image ici

4.3 Analyse des sept paramètres de ThreadPoolExecutor

Insérez la description de l'image ici

  • 1.orePoolSize: le nombre de threads principaux résidents dans le thread

  • 2, maxmunPoolSize: le nombre maximum de threads pouvant être exécutés simultanément dans le pool de threads, cette valeur doit être supérieure à 1

  • 3. KeepAliveTime: le temps de survie des threads inactifs redondants. Lorsque le nombre de threads dans le pool actuel dépasse corePoolSize && lorsque le temps d'inactivité atteint keepAliveTime, les threads supplémentaires seront détruits jusqu'à ce que les threads corePoolSize soient laissés (stratégie excédentaire)

  • 4. unité: unité keepAliveTime

  • 5. workQueue: file d'attente de blocage des tâches, tâches qui ont été soumises mais pas encore exécutées (stratégie insuffisante)

  • 6, threadFactory: représente la fabrique de threads qui génère des threads de travail dans le pool de threads et est utilisée pour créer des threads. Généralement, la valeur par défaut est correcte

  • 7. Gestionnaire: stratégie de rejet, ce qui signifie que lorsque la file d'attente de blocage des tâches est pleine et que le nombre total de threads de travail est supérieur ou égal au nombre maximum de threads dans le pool de threads (maxmunPoolSize), comment refuser la stratégie Runnable (stratégie complète) demandée pour l'exécution

4.4 Principe de fonctionnement de ThreadPoolExecutor

  • 1. Après avoir créé le pool de threads, commencez à attendre les demandes.

  • 2. Lors de l'appel de la méthode execute () pour ajouter une tâche de requête, le pool de threads émettra les jugements suivants:

    2.1 Si le nombre de threads en cours d'exécution est inférieur à corePoolSize, créez immédiatement un thread pour exécuter cette tâche;

    2.2 Si le nombre de threads en cours d'exécution est supérieur ou égal à corePoolSize, mettez la tâche dans la file d'attente;

    2.3 Si la file d'attente est pleine à ce moment et que le nombre de threads en cours d'exécution est toujours inférieur au maximumPoolSize, vous devez toujours créer un thread non-core pour exécuter cette tâche immédiatement;

    2.4 Si la file d'attente est pleine et que le nombre de threads en cours d'exécution est supérieur ou égal à maximumPoolSize, alors le pool de threads lancera la stratégie de rejet de saturation à exécuter.

  • 3. Lorsqu'un thread termine sa tâche, il supprime la tâche suivante de la file d'attente pour exécution.

  • 4. Lorsqu'un thread n'a rien à faire pendant plus d'un certain temps (keepAliveTime), le thread jugera:
    si le nombre de threads en cours d'exécution est supérieur à corePoolSize, alors ce thread sera arrêté.
    Ainsi, une fois toutes les tâches du pool de threads terminées, il finira par se réduire à la taille de corePoolSize.

4.5 Pool de threads personnalisés

Utilisez 7 paramètres pour personnaliser le pool de threads (le paramètre le plus important est la stratégie de rejet)

public class MyThreadPoolDemo {
    
    
    public  static void main(String args[]){
    
    
       ExecutorService threadPool = new ThreadPoolExecutor(2,
                5,
                2L,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
    }
}

Quatre stratégies de rejet majeures:

1. ThreadPoolExecutor.AbortPolicy (); lève RejectExecutionException directement pour empêcher le système de fonctionner normalement

2. ThreadPoolExecutor.CallerRunsPolicy (); L'appelant exécute un mécanisme d'ajustement. Cette stratégie n'abandonne pas les tâches ni ne lève d'exceptions, mais renvoie certaines tâches à l'appelant, réduisant ainsi le flux de nouvelles tâches.

3. ThreadPoolExecutor.DiscardOldestPolicy (); Ignorez la tâche en attente la plus longue de la file d'attente, puis ajoutez la tâche en cours à la file d'attente et essayez de soumettre à nouveau la tâche en cours

4. ThreadPoolExecutor.DiscardPolicy (): Cette stratégie rejette silencieusement les tâches qui ne peuvent pas être traitées, ne gère aucune tâche ou lève des exceptions. Si la tâche est autorisée à être perdue, c'est la meilleure stratégie.

Mécanisme, cette stratégie n'abandonne pas les tâches ni ne lève d'exceptions, mais renvoie certaines tâches à l'appelant, réduisant ainsi le flux de nouvelles tâches

3. ThreadPoolExecutor.DiscardOldestPolicy (); Ignorez la tâche en attente la plus longue de la file d'attente, puis ajoutez la tâche en cours à la file d'attente et essayez de soumettre à nouveau la tâche en cours

4. ThreadPoolExecutor.DiscardPolicy (): Cette stratégie rejette silencieusement les tâches qui ne peuvent pas être traitées, ne gère aucune tâche ou lève des exceptions. Si la tâche est autorisée à être perdue, c'est la meilleure stratégie.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_44634197/article/details/108345736
conseillé
Classement