[Java] Traitement multi-thread - Contrôle exclusif

Faites attention au partage de données dans le traitement multi-thread

Exemple NG

//Exemple NG
public class SynchronizedNotUse {
//Données partagées par plusieurs threads
  private int value = 0;

//Exécuter 100 000 threads
  public static void main(String[] args) {
    final int TASK_NUM = 100000;
    var th = new Thread[TASK_NUM];
    var tb = new SynchronizedNotUse();
    //Création et exécution de threads
    for (var i = 0; i < TASK_NUM; i++) {
      th[i] = new Thread(() -> {
        tb.increment();
      });
      th[i].start();
    }
    //Attendez la fin du fil
    for (var i = 0; i < TASK_NUM; i++) {
      try {
        th[i].join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    System.out.println(tb.value); //Différent à chaque fois
  }
  //Incrémenter le champ de valeur
  void increment() {
    this.value++;
  }
}

Contrôle exclusif avec bloc synchronisé

public class SynchronizedUse {
  private int value = 0;

  public static void main(String[] args) {
    final int TASK_NUM = 100000;
    var th = new Thread[TASK_NUM];
    var tb = new SynchronizedUse();
    for (var i = 0; i < TASK_NUM; i++) {
      th[i] = new Thread(() -> {
        tb.increment();
      });
      th[i].start();
    }
    for (var i = 0; i < TASK_NUM; i++) {
      try {
        th[i].join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    System.out.println(tb.value);
  }
   //Spécifiez l'objet à verrouiller comme instance actuelle
  void increment() {
    synchronized(this) {
      this.value++;
    }
  }
}

modificateur synchronisé

synchronized void increment() {
    this.value++;
}

Verrou explicite

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class LockBasic {
  private int value = 0;
  private final Lock lock = new ReentrantLock();

  public static void main(String[] args) {
    final int TASK_NUM = 100000;
    var th = new Thread[TASK_NUM];
    var tb = new LockBasic();
    for (var i = 0; i < TASK_NUM; i++) {
      th[i] = new Thread(() -> {
        tb.increment();
      });
      th[i].start();
    }
    for (var i = 0; i < TASK_NUM; i++) {
      try {
        th[i].join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }

    System.out.println(tb.value);
  }


  void increment() {
    //Verrouiller l'acquisition
    lock.lock();
    try {
      this.value++;
    } finally {
      //ouvrir
      lock.unlock();
    }
  }
}

** Méthode tryLock **

  if (lock.tryLock(10,TimeUnit.SECONDS)) {
    try {
    //Traitement qui devrait être contrôlé exclusivement
    } finally {
      lock.unlock();
    }
  }else{
  //Que faire si vous ne pouvez pas obtenir de cadenas
}

Contrôle exclusif sans verrouillage

import java.util.concurrent.atomic.AtomicInteger;

public class AtomicBasic {
  private AtomicInteger value = new AtomicInteger();

  public static void main(String[] args) {
    final int TASK_NUM = 100000;
    var th = new Thread[TASK_NUM];
    var tb = new AtomicBasic();
    for (var i = 0; i < TASK_NUM; i++) {
      th[i] = new Thread(() -> {
        tb.increment();
      });
      th[i].start();
    }
    for (var i = 0; i < TASK_NUM; i++) {
      try {
        th[i].join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println(tb.value);
  }

  void increment() {
    value.getAndIncrement();
  }
}

Pool de threads

public class ThreadPool implements Runnable {
  @Override
  public void run() {
    for (var i = 0; i < 30; i++){
      System.out.println(Thread.currentThread().getName() + ":" + i);
    }
  }
}
import java.util.concurrent.Executors;

public class ThreadPoolBasic {

  public static void main(String[] args) {
    //Générer un pool de threads avec 10 threads
    var es = Executors.newFixedThreadPool(10);
    //Appel et exécution avec la méthode d'exécution
    es.execute(new ThreadPool());
    es.execute(new ThreadPool());
    es.execute(new ThreadPool());
    es.shutdown();
  }
}

Planifier l'exécution

import java.time.LocalDateTime;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class ThreadSchedule {
  public static void main(String[] args) {
  //Préparation du pool de threads
    var sche = Executors.newScheduledThreadPool(2);
  //Enregistrement de l'exécution du calendrier
    sche.scheduleAtFixedRate(() -> {
      System.out.println(LocalDateTime.now());
    }, 0, 5, TimeUnit.SECONDS);

    //Suspendre le thread principal en attendant que le programme s'exécute
    try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    //Arrêtez le pool de threads
    sche.shutdown();
  }
}

Recevoir le résultat du traitement du thread

//Trouvez un nombre aléatoire dans un autre thread et faites une pause pendant quelques millisecondes
//Afficher la valeur dans le thread principal
import java.util.Random;
import java.util.concurrent.Callable;

//Callable<Integer>Attribuer un type entier avec
public class ThreadCallable implements Callable<Integer> {
  @Override
  //Code à exécuter dans l'interface appelable
  public Integer call() throws Exception {
    var rnd = new Random();
    var num = rnd.nextInt(1000);
    Thread.sleep(num);
    return num;
  }
}
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;

public class ThreadCallableBasic {

  public static void main(String[] args) {
  //Exécution de thread
    var exe = Executors.newSingleThreadExecutor();
    var r1 = exe.submit(new ThreadCallable());
    var r2 = exe.submit(new ThreadCallable());
    var r3 = exe.submit(new ThreadCallable());

  //Affichage des résultats du fil
    //La valeur de retour de la méthode d'envoi est Future<Integer>
    try {
      System.out.println("r1: " + r1.get());
      System.out.println("r2: " + r2.get());
      System.out.println("r3: " + r3.get());
    } catch (InterruptedException | ExecutionException e) {
      e.printStackTrace();
    }
    exe.shutdown();
  }
}

Post-traitement du traitement des threads

//Trouvez un nombre aléatoire dans un autre thread et faites une pause pendant quelques millisecondes
//Montrez sa valeur

import java.util.Random;
import java.util.concurrent.CompletableFuture;

public class FutureBasic {

  public static void main(String[] args) {
    //Exécution du traitement asynchrone
    CompletableFuture.supplyAsync(() -> {
      var r = new Random();
      var num = r.nextInt(1000);
      heavy(num);
      return num;
    })
      //Traitement après achèvement
      .thenAcceptAsync((result) -> {
        System.out.println(result);
      });
    System.out.println("...Tout post-traitement...");
    heavy(7000);
  }
  //Le traitement factice (lourd) suspend le traitement uniquement pendant la durée spécifiée
  public static void heavy(int num) {
    try {
      Thread.sleep(num);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

Tri des succès / gestion des erreurs

import java.util.Random;
import java.util.concurrent.CompletableFuture;

public class FutureComplete {

  public static void main(String[] args) {
    CompletableFuture.supplyAsync(() -> {
      var r = new Random();
      var num = r.nextInt(1000);
      heavy(num);
      return num;
    })
      .whenCompleteAsync((result, ex) -> {
        //Succès
        if (ex == null) {
          System.out.println(result);
        } else {
        //Échec
          System.out.println(ex.getMessage());
        }
      });
    heavy(7000);
  }

  public static void heavy(int num) {
    try {
      Thread.sleep(num);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

Exécuter plusieurs processus asynchrones en série

import java.util.Random;
import java.util.concurrent.CompletableFuture;

public class FutureSeq {

  public static void main(String[] args) {
  //Processus 1(Génération aléatoire)
    CompletableFuture.supplyAsync(() -> {
      var r = new Random();
      var num = r.nextInt(5000);
      heavy(2000);
      System.out.printf("Processus 1: %d\n", num);
      return num;
    })
  //Processus 2(Temps aléatoires)
    .thenApplyAsync((data) -> {
      var result = data * 2;
      heavy(2000);
      System.out.printf("Processus 2: %d\n", result);
      return result;
    })
  //Processus 3(Double aléatoire)
    .thenAcceptAsync((data) -> {
      var num = data * 2;
      heavy(2000);
      System.out.printf("Processus 3: %d\n", num);
    });
    heavy(7000);
  }

  public static void heavy(int num) {
    try {
      Thread.sleep(num);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

Recommended Posts

[Java] Traitement multi-thread - Contrôle exclusif
[Java] Traitement multi-thread
Syntaxe de contrôle Java
Syntaxe de contrôle Java
Traitement des threads Java
Traitement des chaînes Java
[Java] Traitement de flux
traitement itératif java
[Java] Note sur la syntaxe de contrôle
Traitement des appels du constructeur JAVA
Java aléatoire, divers traitements
Gestion des versions Java sur macOS
Gestion des versions Java avec SDKMAN
Gestion des versions Java avec jenv
[Java] Stream API - Traitement de l'arrêt du flux
[Java] Stream API - Traitement intermédiaire de flux
[Java] Méthode d'implémentation du traitement du minuteur
☾ Instruction Java / Repeat et instruction de contrôle de répétition
Traitement parallèle mesuré avec Java
Comprendre le traitement parallèle Java (Introduction)
[Java] Résumé de la syntaxe de contrôle
Résumé du traitement des erreurs Java
[ev3 × Java] Affichage, son, contrôle LED
Traitement de la date en Java (LocalDate: Initialization)
Déléguer certains traitements Java à JavaScript
[Java] Traitement en boucle et table de quatre-vingt-dix-neuf
Exécutez node.js depuis Android Java (traitement)
[Traitement × Java] Comment utiliser les variables
Remarques sur le contrôle du signal en Java
Traitement serveur avec Java (Introduction partie 1)
Traitement de flux d'inversion de liste Java étonnamment profond
Flux de traitement de base de Java Stream
A propos du traitement de la copie de fichiers en Java
Remarques sur le traitement des threads Android (java)
Suppression de fichiers à l’aide du traitement récursif [Java]
[Traitement × Java] Comment utiliser les tableaux
[Java] Mémo de méthode de mesure du temps de traitement
[Java] Types d'exception et traitement de base
Ceci et cela du contrôle exclusif
[ev3 × Java] Commande de moteur unique