Concurrence, BlockingQueues (Java 7) - 1

« Salut Amigo ! »

« Salut, Kim ! »

"Aujourd'hui, je vais vous parler de la concurrence."

" Concurrency est une bibliothèque de classes Java qui comprend des classes spéciales qui ont été optimisées pour le travail à partir de plusieurs threads. C'est un sujet très intéressant et très complet. Mais aujourd'hui, nous allons juste avoir une introduction. Le package s'appelle java.util. package simultané. Je vais vous parler de quelques cours intéressants. »

" Types atomiques. "

"Vous savez déjà que même count++ n'est pas une opération thread-safe. Lorsqu'une variable est incrémentée de 1, trois opérations ont réellement lieu. Par conséquent, il peut y avoir un conflit lorsque la variable est modifiée."

« Ouais, Ellie m'a dit il n'y a pas longtemps : »

Sujet 1 Fil 2 Résultat
register1 = count;
register1++;
count = register1;
register2 = count;
register2++;
count = register2;
register1 = count;
register2 = count;
register2++;
count = register2;
register1++;
count = register1;

"Exactement. Ensuite, Java a ajouté des types de données pour effectuer ces opérations comme une seule, c'est-à-dire de manière atomique (un atome est indivisible)."

"Par exemple, Java a AtomicInteger, AtomicBoolean, AtomicDouble , etc."

"Supposons que nous ayons besoin de créer une classe "counter":"

Exemple
class Counter
{
 private int c = 0;

 public void increment()
 {
  c++;
 }

 public void decrement()
 {
  c--;
 }

 public int value()
 {
  return c;
 }
}

"Comment feriez-vous pour rendre les objets de cette classe thread-safe ?"

"Eh bien, je ferais en sorte que toutes les méthodes soient synchronisées et j'en aurais fini :"

Exemple
class synchronized Counter
{
 private int c = 0;

 public synchronized void increment()
 {
  c++;
 }

 public synchronized void decrement()
 {
  c--;
 }

 public synchronized int value()
 {
  return c;
 }
}

"Bon travail. Mais, à quoi cela ressemblerait-il si nous utilisions des types atomiques :"

Exemple
class AtomicCounter
{
 private AtomicInteger c = new AtomicInteger(0);

 public void increment()
 {
  c.incrementAndGet();
 }

 public void decrement()
 {
  c.decrementAndGet();
 }

 public int value()
 {
  return c.get();
 }
}

"Votre classe et ma classe fonctionnent toutes les deux de la même manière, mais la classe avec un AtomicInteger fonctionne plus rapidement."

"Eh bien, est-ce une petite différence?"

"Oui. D'après mon expérience, je recommande toujours de diriger avec synchronized. Ce n'est que lorsque tout le code de l'application a été écrit et que le processus d'optimisation a commencé que vous devriez commencer à réécrire le code pour utiliser les types atomiques. Mais dans tous les cas, je voulais que vous de savoir que de tels types existent. Même si vous ne les utilisez pas activement, il y a toujours une chance que vous rencontriez du code là où ils sont utilisés.

"Je suis d'accord. C'est logique."

"Au fait, avez-vous remarqué que les types atomiques ne sont pas immuables ? Contrairement à la classe Integer standard , AtomicInteger contient des méthodes permettant de modifier son état interne."

"Compris. Tout comme String et StringBuffer ."

"Oui, quelque chose comme ça."

" Collections thread-safe. "

"Comme exemple d'une telle collection, puis-je présenter ConcurrentHashMap. Comment feriez-vous pour rendre HashMap thread-safe ?"

"Faire en sorte que toutes ses méthodes soient synchronisées ?"

"Bien sûr, mais imaginez maintenant que vous avez un tel SynchronizedHashMap, et des dizaines de threads y accédant. Et cent fois par seconde, une nouvelle entrée est ajoutée à la carte, et dans le processus, l'objet entier est verrouillé pour la lecture et l'écriture."

"Eh bien, c'est l'approche standard. Que pouvez-vous faire?"

"Les créateurs de Java ont proposé quelques trucs sympas."

"Tout d'abord, ils stockent les données dans un ConcurrentHashMap dans un seul bloc, mais le divisent en parties appelées "buckets". mots, de nombreux threads peuvent changer l'objet simultanément."

"Deuxièmement, vous souvenez-vous que vous ne pouvez pas itérer sur les éléments de la liste/carte et modifier la liste en même temps ? Un tel code lèvera une exception :"

Ne pas itérer sur les éléments d'une collection dans une boucle et la modifier simultanément
HashMap<String, Integer> map = new HashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"Mais dans ConcurrentHashMap, vous pouvez :"

Ne parcourez pas les éléments d'une collection dans une boucle et modifiez-la simultanément"
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();

for (String key: map.keySet())
{
 if (map.get(key) == 0)
  map.remove(key);
}

"Le package concurrent présente de nombreux avantages. Il suffit de bien comprendre ces classes pour pouvoir les utiliser."

"Je vois. Merci, Kim. Ce sont des cours vraiment intéressants. J'espère qu'un jour je les maîtriserai comme un virtuose."