Depuis que j'ai lu "Design Patterns Learned in Java Language (Multithread Edition)", je vais enregistrer les principaux points.
--Méthode 1 Utilisez la classe java.lang.Thread.
Le comportement du thread nouvellement démarré est décrit dans la méthode ** run ** de la classe ** Thread **. L'appel de la méthode ** start ** de la classe Thread démarrera un nouveau thread. Lorsque vous appelez la méthode start, un nouveau thread est démarré et la méthode run est appelée.
public class Main {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
for (int i = 0; i < 100; i++) {
System.out.print("1");
}
}
public static class MyThread extends Thread {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("2");
}
}
}
}
Première fois
Résultat d'exécution
11111111111111111111111111111111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111111111111111111111111111111111111111222222
Deuxième fois
Résultat d'exécution
11111222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222211111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
--Méthode 2 Utiliser l'interface Runnbale
Démarrez un thread à l'aide d'une instance d'une classe qui implémente l'interface ** Runnable **. L'interface Runnable est déclarée comme suit:
public interface Runnable {
public abstract void run();
}
Créez une classe qui implémente l'interface Runnbale, transmettez l'instance au constructeur Thread et appelez la méthode start.
public class Main {
public static void main(String[] args) {
Runnable myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
for (int i = 0; i < 100; i++) {
System.out.print("1");
}
}
public static class MyThread implements Runnable {
public void run() {
for (int i = 0; i < 100; i++) {
System.out.print("2");
}
}
}
}
Utilisez Thread.sleep. Placez l'appel de la méthode ** sleep ** dans try-catch. La méthode sleep lève une exception ** InterruptedException **.
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.print("1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
}
}
Le comportement de thread inattendu provoqué par la concurrence (race) entre le thread A et le thread B est appelé ** course de données **. Le contrôle du trafic est nécessaire pour empêcher les traces de données, communément appelées ** contrôle exclusif **. En Java, le mot clé ** synchronized ** est utilisé lors du contrôle exclusif des threads. Si vous déclarez une méthode avec le mot clé synchronized, la méthode s'exécutera dans un seul thread. Ces méthodes sont appelées ** méthode synchronisée ** et ** méthode synchronisée **.
public class Bank {
private int money;
private String name;
public Bank(String name, int money) {
this.name = name;
this.money = money;
}
//Faire un dépôt
public synchronized void deposit(int m) { //Méthode synchrone
money += m;
}
//Extraire
public synchronized boolean withdraw(int m) { //Méthode synchrone
if (money >= m) {
money -= m;
return true;
} else {
return false;
}
}
public String getName() {
return name;
}
}
Si même un thread a un ** verrou **, aucun autre thread ne peut entrer. Le verrou est ** libéré ** lorsque le thread qui exécutait la méthode synchronisée finit d'exécuter cette méthode. Lorsque le verrou est libéré, n'importe lequel des threads qui était précédemment verrouillé et qui n'a pas pu être entré peut prendre le verrou.
Des verrous existent pour chaque instance. L'exécution de la méthode synchronisée d'une instance ne signifie pas que la méthode synchronisée d'une autre instance ne peut pas être exécutée.
Vous pouvez vérifier si le thread actuel a un verrou sur un objet avec la méthode Thread.holdsLock.
Utilisez le ** bloc synchronisé ** si vous souhaitez que certaines des méthodes fonctionnent dans un seul thread au lieu de la méthode entière.
synchronized (formule) {
...
}
Les éléments suivants sont équivalents
synchronized void method() {
...
}
void method() {
synchronized (this) {
...
}
}
Les éléments suivants sont équivalents
class Something {
static synchronized void method() {
....
}
}
class Something {
static void method() {
synchronized (Something.class) {
....
}
}
}
Chaque instance a un ** jeu de poids **. Un ensemble de poids est un ensemble de threads qui exécutent la méthode ** wait ** de cette instance et sont arrêtés. C'est comme une salle d'attente de thread pour chaque instance. Lorsque le thread exécute la méthode d'attente, il interrompt son opération et entre dans une salle d'attente appelée ensemble d'attente. Le thread attend dans son jeu de poids jusqu'à ce que l'un des événements suivants se produise:
Par exemple obj.wait(); Lorsque l'instruction est exécutée, le thread actuel est suspendu et l'ensemble d'attente de l'instance obj est entré. Ceci est dit que le thread attend sur obj. Le thread doit avoir un verrou pour exécuter la méthode wait.
L'ensemble de poids est un concept virtuel. Il n'existe aucune méthode pour obtenir une liste de threads pondérés sur une instance.
(Il y a un diagramme dans ce livre qui décrit ce concept d'une manière facile à comprendre, alors veuillez vous y référer.)
Utilisez la méthode ** notify ** pour supprimer l'un des fils du jeu de poids du jeu de poids. Par exemple obj.notify(); Est exécuté par un thread. Ensuite, un thread est sélectionné parmi les threads de l'ensemble de poids d'obj, et ce thread est réveillé. Le fil réveillé sort du jeu de poids. Le thread doit avoir un verrou pour exécuter la méthode de notification. ** Un thread généré par notify ne reprend pas l'exécution au moment où il est notifié. ** Parce que le thread notifié a le verrou au moment de la notification. ** Lorsque la méthode de notification est exécutée, s'il y a plusieurs threads en attente dans l'ensemble d'attente, quel thread est sélectionné n'est pas spécifié dans les spécifications. ** **
Utilisez la méthode notifyAll pour amener tous les fils du poids défini hors du jeu de poids. Comme la méthode wait et la méthode norify, la méthode notifyAll ne peut être appelée qu'à partir du thread qui a le verrou de l'instance à appeler. Comme notifier, le thread qui est sorti n'est pas redémarré immédiatement. Une fois que le thread qui a exécuté notifyAll a libéré le verrou, un seul thread chanceux peut reprendre l'exécution.
Une exception ** java.lang.IllegalMonitorStateException ** est levée lorsqu'un thread qui n'a pas de verrou appelle wait, notify, notifyAll.
Le thread a les états suivants.
--NEW: état des threads non démarrés --RUNNABLE: état des threads en cours d'exécution sur les machines virtuelles Java --TERMINATED: état du thread terminé --WAITING: l'état d'un thread qui attend indéfiniment qu'un autre thread exécute une action particulière. --TIMED_WAITING: état du thread en attente d'un autre thread pour effectuer une action pendant le temps d'attente spécifié --BLOCKED: état des threads bloqués et en attente d'un verrouillage du moniteur
Ces états peuvent être obtenus avec la méthode getState de la classe Thread.
Le code source peut être téléchargé à partir de HP de l'auteur. http://www.hyuki.com
Recommended Posts