Maison  >  Article  >  Java  >  Compréhension approfondie des méthodes de communication entre les threads dans le multi-threading JAVA

Compréhension approfondie des méthodes de communication entre les threads dans le multi-threading JAVA

高洛峰
高洛峰original
2017-01-05 17:00:291888parcourir

1. Introduction

Ce résumé résume ma compréhension des méthodes de communication entre les threads dans le multi-threading JAVA. Je discute principalement de la communication entre les threads en utilisant du code combiné avec du texte, j'en ai donc extrait quelques-uns du livre. Exemple de code.

2. Méthodes de communication entre les threads

① Synchronisation

La synchronisation mentionnée ici fait référence à la communication entre plusieurs threads via le mot-clé synchronisé.

Exemple de référence :

public class MyObject {
 
  synchronized public void methodA() {
    //do something....
  }
 
  synchronized public void methodB() {
    //do some other thing
  }
}
 
public class ThreadA extends Thread {
 
  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodA();
  }
}
 
public class ThreadB extends Thread {
 
  private MyObject object;
//省略构造方法
  @Override
  public void run() {
    super.run();
    object.methodB();
  }
}
 
public class Run {
  public static void main(String[] args) {
    MyObject object = new MyObject();
 
    //线程A与线程B 持有的是同一个对象:object
    ThreadA a = new ThreadA(object);
    ThreadB b = new ThreadB(object);
    a.start();
    b.start();
  }
}

Puisque le thread A et le thread B contiennent le même objet de la classe MyObject, bien que les deux threads doivent appeler des méthodes différentes, ils sont exécutés de manière synchrone. Par exemple : Le thread B doit attendre que le thread A ait fini d'exécuter la méthode methodA() avant de pouvoir exécuter la méthode methodB(). De cette façon, le thread A et le thread B établissent la communication.

Cette méthode est essentiellement une communication à « mémoire partagée ». Plusieurs threads doivent accéder à la même variable partagée. Celui qui obtient le verrou (obtient l'autorisation d'accès) peut l'exécuter.

②while méthode d'interrogation

Le code est le suivant :

import java.util.ArrayList;
import java.util.List;
 
public class MyList {
 
  private List<String> list = new ArrayList<String>();
  public void add() {
    list.add("elements");
  }
  public int size() {
    return list.size();
  }
}
 
import mylist.MyList;
 
public class ThreadA extends Thread {
 
  private MyList list;
 
  public ThreadA(MyList list) {
    super();
    this.list = list;
  }
 
  @Override
  public void run() {
    try {
      for (int i = 0; i < 10; i++) {
        list.add();
        System.out.println("添加了" + (i + 1) + "个元素");
        Thread.sleep(1000);
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}
 
import mylist.MyList;
 
public class ThreadB extends Thread {
 
  private MyList list;
 
  public ThreadB(MyList list) {
    super();
    this.list = list;
  }
 
  @Override
  public void run() {
    try {
      while (true) {
        if (list.size() == 5) {
          System.out.println("==5, 线程b准备退出了");
          throw new InterruptedException();
        }
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}
 
import mylist.MyList;
import extthread.ThreadA;
import extthread.ThreadB;
 
public class Test {
 
  public static void main(String[] args) {
    MyList service = new MyList();
 
    ThreadA a = new ThreadA(service);
    a.setName("A");
    a.start();
 
    ThreadB b = new ThreadB(service);
    b.setName("B");
    b.start();
  }
}

De cette façon, le thread A modifie continuellement les conditions et le thread ThreadB continue de transmettre l'instruction while Check si cette condition (list.size()==5) est vraie, réalisant ainsi la communication entre les threads. Mais cette méthode gaspillera les ressources du processeur. La raison pour laquelle il s'agit d'un gaspillage de ressources est que lorsque le planificateur JVM confie le processeur au thread B pour exécution, il n'effectue aucun travail "utile". Il teste simplement en permanence si une certaine condition est vraie. C'est similaire à la façon dont dans la vraie vie, une personne continue de regarder l'écran du téléphone pour voir si un appel arrive, au lieu de : faire autre chose. Lorsqu'un appel arrive, le téléphone sonne pour l'avertir que l'appel arrive.

③mécanisme d'attente/notification

Le code est le suivant :

import java.util.ArrayList;
import java.util.List;
 
public class MyList {
 
  private static List<String> list = new ArrayList<String>();
 
  public static void add() {
    list.add("anyString");
  }
 
  public static int size() {
    return list.size();
  }
}
 
 
public class ThreadA extends Thread {
 
  private Object lock;
 
  public ThreadA(Object lock) {
    super();
    this.lock = lock;
  }
 
  @Override
  public void run() {
    try {
      synchronized (lock) {
        if (MyList.size() != 5) {
          System.out.println("wait begin "
              + System.currentTimeMillis());
          lock.wait();
          System.out.println("wait end "
              + System.currentTimeMillis());
        }
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}
 
 
public class ThreadB extends Thread {
  private Object lock;
 
  public ThreadB(Object lock) {
    super();
    this.lock = lock;
  }
 
  @Override
  public void run() {
    try {
      synchronized (lock) {
        for (int i = 0; i < 10; i++) {
          MyList.add();
          if (MyList.size() == 5) {
            lock.notify();
            System.out.println("已经发出了通知");
          }
          System.out.println("添加了" + (i + 1) + "个元素!");
          Thread.sleep(1000);
        }
      }
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}
 
public class Run {
 
  public static void main(String[] args) {
 
    try {
      Object lock = new Object();
 
      ThreadA a = new ThreadA(lock);
      a.start();
 
      Thread.sleep(50);
 
      ThreadB b = new ThreadB(lock);
      b.start();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

Le thread A doit attendre qu'une certaine condition soit remplie (list.size()= =5) avant d'exécuter l'opération. Le fil B ajoute des éléments à la liste et modifie la taille de la liste.

Comment A et B communiquent-ils ? En d’autres termes, comment le thread A sait-il que list.size() vaut déjà 5 ?

Les méthodes wait() et notify() de la classe Object sont utilisées ici.

Lorsque la condition n'est pas remplie (list.size() !=5), le thread A appelle wait() pour abandonner le CPU et entrer dans l'état de blocage. ---Il n'occupe pas le CPU comme ②pendant l'interrogation

Lorsque les conditions sont remplies, le thread B appelle notify() pour notifier le thread A. Le soi-disant thread de notification A consiste à réveiller le thread A et à laisser il entre dans l'état exécutable.

L'un des avantages de cette méthode est que le taux d'utilisation du processeur est amélioré.

Mais il y a aussi quelques défauts : par exemple, le thread B s'exécute en premier, ajoute 5 éléments à la fois et appelle notify() pour envoyer une notification, alors que le thread A est toujours en cours d'exécution à ce moment-là ; et appelle wait(), alors il ne pourra jamais être réveillé. Parce que le fil B a déjà envoyé une notification et n'enverra plus de notifications à l'avenir. Cela montre qu'une notification trop précoce perturbera la logique d'exécution du programme.

L'article ci-dessus fournit une compréhension approfondie des méthodes de communication entre les threads dans le multi-threading JAVA, c'est-à-dire tout le contenu partagé par l'éditeur. J'espère qu'il pourra vous donner une référence, et j'espère que vous le ferez. prendra en charge le site Web chinois PHP.

Pour une compréhension plus approfondie des méthodes de communication entre les multi-threads JAVA et les articles associés, veuillez faire attention au site Web PHP chinois !


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn