window.pipedriveLeadboosterConfig = { base : 'leadbooster-chat.pipedrive.com', companyId : 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version : 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster existe déjà') } else { w.LeadBooster = { q : [], on : function (n, h) { this.q.push({ t : 'o', n : n, h : h }) }, trigger : function (n) { this.q.push({ t : 't', n : n }) }, } } })() Concurrence en Java Partie 1 - Introduction - The Codest
The Codest
  • A propos de nous
  • Services
    • Développement de logiciels
      • Développement frontal
      • Développement backend
    • Staff Augmentation
      • Développeurs frontaux
      • Développeurs backend
      • Ingénieurs des données
      • Ingénieurs en informatique dématérialisée
      • Ingénieurs AQ
      • Autres
    • Conseil consultatif
      • Audit et conseil
  • Industries
    • Fintech et banque
    • E-commerce
    • Adtech
    • Santé (Healthtech)
    • Fabrication
    • Logistique
    • Automobile
    • IOT
  • Valeur pour
    • CEO
    • CTO
    • Gestionnaire des livraisons
  • Notre équipe
  • Études de cas
  • Savoir comment
    • Blog
    • Rencontres
    • Webinaires
    • Ressources
Carrières Prendre contact
  • A propos de nous
  • Services
    • Développement de logiciels
      • Développement frontal
      • Développement backend
    • Staff Augmentation
      • Développeurs frontaux
      • Développeurs backend
      • Ingénieurs des données
      • Ingénieurs en informatique dématérialisée
      • Ingénieurs AQ
      • Autres
    • Conseil consultatif
      • Audit et conseil
  • Valeur pour
    • CEO
    • CTO
    • Gestionnaire des livraisons
  • Notre équipe
  • Études de cas
  • Savoir comment
    • Blog
    • Rencontres
    • Webinaires
    • Ressources
Carrières Prendre contact
Flèche arrière RETOUR
2022-06-15
Développement de logiciels

Concurrence en Java Partie 1 - Introduction

The Codest

Rafal Sawicki

Développeur Java

Lisez la première partie de notre série de blogs consacrée à la concurrence en Java. Dans l'article suivant, nous examinerons de plus près les différences entre les threads et les processus, les pools de threads, les exécuteurs et bien d'autres choses encore !

En général, l'approche conventionnelle de la programmation est séquentielle. Dans un programme, tout se passe étape par étape.
Mais, en fait, le parallèle est le mode de fonctionnement du monde entier - c'est la capacité d'exécuter plus d'une tâche simultanément.

Fil ou processus

Pour discuter de sujets avancés tels que la concurrence dans Java ou le multithreading, nous devons nous mettre d'accord sur des définitions communes pour être sûrs d'être sur la même longueur d'onde.

Commençons par les bases. Dans le monde non séquentiel, nous disposons de deux types de représentants de la concurrence : les processus et les
threads. Un processus est une instance du programme en cours d'exécution. Normalement, il est isolé des autres processus.
Le système d'exploitation est responsable de l'attribution des ressources à chaque processus. En outre, il agit comme un chef d'orchestre qui
les planifie et les contrôle.

Le thread est une sorte de processus mais à un niveau inférieur, c'est pourquoi il est également connu sous le nom de thread léger. Plusieurs threads peuvent s'exécuter dans un
processus. Dans ce cas, le programme agit comme un planificateur et un contrôleur pour les threads. De cette manière, les programmes individuels semblent faire
plusieurs tâches en même temps.

La différence fondamentale entre les threads et les processus est le niveau d'isolation. Le processus dispose de son propre ensemble de
tandis que le thread partage des données avec d'autres threads. Cette approche peut sembler sujette aux erreurs, et c'est effectivement le cas. En effet, pour
mais ne nous attardons pas sur ce point, qui dépasse le cadre de cet article.

Processus, threads - d'accord... Mais qu'est-ce que la simultanéité ? La simultanéité signifie que vous pouvez exécuter plusieurs tâches en même temps.
temps. Cela ne signifie pas que ces tâches doivent être exécutées simultanément - c'est ce qu'on appelle le parallélisme. Concurrenc dans Javay n'est pas non plus
ne nécessite pas de disposer de plusieurs unités centrales ou même de plusieurs cœurs. Il est possible d'y parvenir dans un environnement à un seul cœur en tirant parti de la technologie
le changement de contexte.

Le multithreading est un terme lié à la concurrence. Il s'agit d'une caractéristique des programmes qui leur permet d'exécuter plusieurs tâches à la fois. Tous les programmes n'utilisent pas cette approche, mais ceux qui le font peuvent être qualifiés de multithreads.

Nous sommes presque prêts à partir, il ne reste plus qu'une définition. L'asynchronisme signifie qu'un programme effectue des opérations non bloquantes.
Il initie une tâche et passe ensuite à autre chose en attendant la réponse. Lorsqu'il reçoit la réponse, il peut y réagir.

Tout ce jazz

Par défaut, chaque Application Java s'exécute dans un seul processus. Dans ce processus, il y a un fil d'exécution lié à l'application main() méthode de
une application. Cependant, comme nous l'avons mentionné, il est possible d'exploiter les mécanismes de threads multiples au sein d'une même application.
programme.

Exécutables

Fil est un Java dans laquelle la magie opère. Il s'agit de la représentation de l'objet du fil de discussion mentionné ci-dessus. Pour
créer votre propre thread, vous pouvez étendre la fonction Fil classe. Toutefois, cette approche n'est pas recommandée. Fils doit être utilisé comme mécanisme d'exécution de la tâche. Les tâches sont des éléments de code que nous voulons exécuter en mode concurrent. Nous pouvons les définir à l'aide de la fonction Exécutables l'interface.

Mais trêve de théorie, joignons le geste à la parole.

Problème

Supposons que nous ayons deux tableaux de nombres. Pour chaque tableau, nous voulons connaître la somme des nombres qu'il contient. Soit
Supposons qu'il existe un grand nombre de tableaux de ce type et que chacun d'entre eux est relativement volumineux. Dans ces conditions, nous voulons utiliser la concurrence et additionner chaque tableau comme une tâche distincte.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ;
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10} ;
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7} ;

Runnable task1 = () -> {
    int sum = Arrays.stream(a1).sum() ;
    System.out.println("1. La somme est : " + sum) ;
} ;

Exécutable task2 = () -> {
    int sum = Arrays.stream(a2).sum() ;
    System.out.println("2. La somme est : " + sum) ;
} ;

Exécutable task3 = () -> {
    int sum = Arrays.stream(a3).sum() ;
    System.out.println("3. La somme est : " + sum) ;
} ;

new Thread(task1).start() ;
new Thread(task2).start() ;
new Thread(task3).start() ;

Comme vous pouvez le voir dans le code ci-dessus Exécutables est une interface fonctionnelle. Elle contient une seule méthode abstraite exécuter()
sans arguments. Les Exécutables doit être mise en œuvre par toute classe dont les instances sont censées être des
exécuté par un thread.

Une fois que vous avez défini une tâche, vous pouvez créer un thread pour l'exécuter. Pour ce faire, il suffit d'utiliser la commande nouveau Thread() qui
prend Exécutables comme argument.

La dernière étape consiste à démarrer() une discussion nouvellement créée. Dans l'API, il y a aussi exécuter() méthodes en Exécutables et en
Fil. Cependant, ce n'est pas une façon de tirer parti de la concurrence en Java. Un appel direct à chacune de ces méthodes se traduit par
l'exécution de la tâche dans le même thread que le main() s'exécute.

Pools de threads et exécuteurs

Lorsqu'il y a beaucoup de tâches, il n'est pas judicieux de créer un fil de discussion distinct pour chacune d'entre elles. La création d'un Fil est un
Il est donc préférable de réutiliser les threads existants plutôt que d'en créer de nouveaux.

Lorsqu'un programme crée de nombreux threads de courte durée, il est préférable d'utiliser un pool de threads. Le pool de threads contient un certain nombre de
les fils de discussion prêts à être exécutés mais qui ne sont pas encore actifs. L'attribution d'un Exécutables au pool, l'un des threads appelle la fonction
exécuter() d'une méthode donnée Exécutables. Après avoir terminé une tâche, le thread existe toujours et se trouve dans un état d'inactivité.

Ok, vous l'avez compris - préférez le pool de threads à la création manuelle. Mais comment utiliser les pools de threads ? Les Exécuteurs
possède un certain nombre de méthodes d'usine statiques pour construire des pools de threads. Par exemple, la méthode newCachedThredPool() crée
un pool dans lequel de nouveaux threads sont créés en fonction des besoins et où les threads inactifs sont conservés pendant 60 secondes. En revanche,
newFixedThreadPool() contient un ensemble fixe de threads, dans lequel les threads inactifs sont conservés indéfiniment.

Voyons comment cela pourrait fonctionner dans notre exemple. Désormais, nous n'avons plus besoin de créer des fils de discussion manuellement. Au lieu de cela, nous devons créer
ExecutorService qui fournit un pool de threads. Nous pouvons ensuite lui assigner des tâches. La dernière étape consiste à fermer le thread
pour éviter les fuites de mémoire. Le reste du code précédent reste inchangé.

ExecutorService executor = Executors.newCachedThreadPool() ;

executor.submit(task1) ;
executor.submit(task2) ;
executor.submit(task3) ;

executor.shutdown() ;

Appelable

Exécutables semble être un moyen astucieux de créer des tâches concurrentes, mais il présente un défaut majeur. Elle ne peut pas renvoyer de
valeur. De plus, nous ne pouvons pas déterminer si une tâche est terminée ou non. Nous ne savons pas non plus si elle est terminée
normalement ou exceptionnellement. La solution à ces maux est Appelable.

Appelable est similaire à Exécutables d'une certaine manière, il englobe également les tâches asynchrones. La principale différence est qu'il est capable de
renvoie une valeur. La valeur de retour peut être de n'importe quel type (non primitif) comme l'indique l'attribut Appelable est un type paramétré.
Appelable est une interface fonctionnelle qui a call() qui peut déclencher un Exception.

Voyons maintenant comment nous pouvons tirer parti de l'effet de levier Appelable dans notre problème de tableau.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ;
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10} ;
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7} ;

Callable task1 = () -> Arrays.stream(a1).sum() ;
Callable task2 = () -> Arrays.stream(a2).sum() ;
Callable task3 = () -> Arrays.stream(a3).sum() ;

ExecutorService executor = Executors.newCachedThreadPool() ;
Future future1 = executor.submit(task1) ;
Future future2 = executor.submit(task2) ;
Future future3 = executor.submit(task3) ;

System.out.println("1. La somme est : " + future1.get()) ;
System.out.println("2. la somme est : " + future2.get()) ;
System.out.println("3. la somme est : " + future3.get()) ;

executor.shutdown() ;

D'accord, nous pouvons voir comment Appelable est créé et soumis à l'autorité compétente de l ExecutorService. Mais qu'est-ce que c'est que L'avenir?
L'avenir agit comme un pont entre les threads. La somme de chaque tableau est produite dans un thread séparé et nous avons besoin d'un moyen pour
de renvoyer ces résultats à main().

Pour récupérer le résultat de L'avenir nous devons appeler get() méthode. Ici, deux choses peuvent se produire. Premièrement, la méthode
le résultat du calcul effectué par Appelable est disponible. Nous l'obtenons alors immédiatement. Deuxièmement, le résultat n'est pas
encore prêt. Dans ce cas, les get() se bloquera jusqu'à ce que le résultat soit disponible.

ComputableFuture

Le problème avec L'avenir est qu'il fonctionne selon le "paradigme de la poussée". Lorsque l'on utilise L'avenir il faut être comme un patron qui
demande constamment : "Votre tâche est-elle accomplie ? Est-elle prête ?" jusqu'à ce qu'elle fournisse un résultat. Agir sous une pression constante, c'est
coûteux. La meilleure solution serait de commander L'avenir ce qu'il doit faire lorsqu'il est prêt à accomplir sa tâche. Malheureusement,
L'avenir ne peut pas le faire, mais ComputableFuture peut.

ComputableFuture fonctionne selon le paradigme "pull". Nous pouvons lui dire ce qu'il doit faire du résultat lorsqu'il a accompli ses tâches. Il
est un exemple d'approche asynchrone.

ComputableFuture fonctionne parfaitement avec Exécutables mais pas avec Appelable. Au lieu de cela, il est possible de fournir une tâche à
ComputableFuture sous forme de Fournisseur.

Voyons comment ce qui précède s'applique à notre problème.

int[] a1 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10} ;
int[] a2 = {10, 10, 10, 10, 10, 10, 10, 10, 10} ;
int[] a3 = {3, 4, 3, 4, 3, 4, 2, 1, 3, 7} ;

CompletableFuture.supplyAsync(() -> Arrays.stream(a1).sum())
                .thenAccept(System.out::println) ;

CompletableFuture.supplyAsync(() -> Arrays.stream(a2).sum())
                .thenAccept(System.out::println) ;

CompletableFuture.supplyAsync(() -> Arrays.stream(a3).sum())
                .thenAccept(System.out::println) ;

La première chose qui frappe, c'est que cette solution est beaucoup plus courte. En outre, elle a un aspect soigné et ordonné.

Tâche à CompletableFuture peut être fournie par supplyAsync() qui prend en compte la méthode Fournisseur ou par runAsync() que
prend Exécutables. Un rappel - un morceau de code qui doit être exécuté à la fin d'une tâche - est défini par thenAccept()
méthode.

Conclusions

Java propose un grand nombre d'approches différentes de la concurrence. Dans cet article, nous n'avons fait qu'effleurer le sujet.

Néanmoins, nous avons couvert les bases de Fil, Exécutables, Appelableet CallableFuture ce qui constitue un bon point
pour un examen plus approfondi du sujet.

Articles connexes

Développement de logiciels

9 erreurs à éviter lors de la programmation en Java

Quelles sont les erreurs à éviter lors de la programmation en Java ? Dans l'article suivant, nous répondons à cette question.

The Codest
Rafal Sawicki Développeur Java
Solutions pour les entreprises et les grandes entreprises

La bonne façon de trouver les meilleurs développeurs Java

Trouver le parfait développeur Java peut s'avérer une tâche ardue. Alors que la demande du marché pour de tels professionnels croît à un rythme effréné, les sources disponibles pour la recherche de talents peuvent parfois sembler...

The Codest
Grzegorz Rozmus Chef d'unité Java
Solutions pour les entreprises et les grandes entreprises

10 entreprises de Dubaï à surveiller en 2020

Dubaï est le cœur des Émirats arabes unis, avec son marché de plus en plus prospère d'entreprises mondiales et de start-ups prometteuses. Nombre d'entre elles peuvent se vanter de leur succès international et de leurs produits remarquables....

Thon Pinar
Solutions pour les entreprises et les grandes entreprises

Comment Java peut soutenir votre entreprise ?

Avant de commencer, j'aimerais vous rappeler une chose importante. Java n'est pas seulement un langage de programmation.

Bartlomiej Kuczynski
Solutions pour les entreprises et les grandes entreprises

Une journée dans la vie d'un programmeur chez The Codest

On pourrait penser que les horaires de travail des programmeurs ne diffèrent pas les uns des autres. Mais ce n'est pas le cas ! Chaque startup, éditeur de logiciels ou même entreprise a ses propres...

The Codest
Pawel Rybczynski Software Engineer

Abonnez-vous à notre base de connaissances et restez au courant de l'expertise du secteur des technologies de l'information.

    A propos de nous

    The Codest - Entreprise internationale de développement de logiciels avec des centres technologiques en Pologne.

    Royaume-Uni - Siège

    • Bureau 303B, 182-184 High Street North E6 2JA
      Londres, Angleterre

    Pologne - Les pôles technologiques locaux

    • Parc de bureaux Fabryczna, Aleja
      Pokoju 18, 31-564 Kraków
    • Brain Embassy, Konstruktorska
      11, 02-673 Varsovie, Pologne

      The Codest

    • Accueil
    • A propos de nous
    • Services
    • Études de cas
    • Savoir comment
    • Carrières
    • Dictionnaire

      Services

    • Conseil consultatif
    • Développement de logiciels
    • Développement backend
    • Développement frontal
    • Staff Augmentation
    • Développeurs backend
    • Ingénieurs en informatique dématérialisée
    • Ingénieurs des données
    • Autres
    • Ingénieurs AQ

      Ressources

    • Faits et mythes concernant la coopération avec un partenaire externe de développement de logiciels
    • Des États-Unis à l'Europe : Pourquoi les startups américaines décident-elles de se délocaliser en Europe ?
    • Comparaison des pôles de développement Tech Offshore : Tech Offshore Europe (Pologne), ASEAN (Philippines), Eurasie (Turquie)
    • Quels sont les principaux défis des CTO et des DSI ?
    • The Codest
    • The Codest
    • The Codest
    • Privacy policy
    • Conditions d'utilisation du site web

    Copyright © 2025 par The Codest. Tous droits réservés.

    fr_FRFrench
    en_USEnglish de_DEGerman sv_SESwedish da_DKDanish nb_NONorwegian fiFinnish pl_PLPolish arArabic it_ITItalian jaJapanese ko_KRKorean es_ESSpanish nl_NLDutch etEstonian elGreek fr_FRFrench