Notes d'étude de fin Java lors du blocage

Un thread peut avoir les quatre états suivants:
1: Nouveau (nouveau): Lorsque le thread est créé, il ne sera dans cet état que pendant une courte période. À ce stade, il a alloué les ressources système nécessaires et effectué l'initialisation. À ce moment, le thread est déjà éligible pour le temps processeur, puis le planificateur transformera ce thread en un état exécutable ou bloqué.

2: Prêt (exécutable): dans cet état, tant que le planificateur alloue des tranches de temps aux threads, les threads peuvent s'exécuter. En d'autres termes, à tout moment, le thread peut ou non s'exécuter. Tant que le planificateur peut allouer des tranches de temps aux threads, il peut s'exécuter, ce qui est différent des états morts et bloqués.

3: Bloqué: le thread peut s'exécuter, mais certaines conditions l'empêchent de s'exécuter. Lorsqu'un thread est dans un état bloqué, le planificateur ignorera le thread et n'allouera pas de temps CPU au thread. Il ne sera pas possible d'effectuer des opérations tant que le thread ne reviendra pas à l'état prêt.

4: Dead (Dead): Le thread à l'état mort ou terminé sera planifiable lorsqu'il est parti, et n'obtiendra pas de temps processeur, sa tâche est terminée ou n'est plus exécutable, comme d'habitude lorsque la tâche meurt Retourne de la méthode run (), mais le thread de la tâche peut toujours être interrompu, comme vous le verrez.

L'entrée dans l'état de blocage peut avoir les raisons suivantes:

1: dormir dormir.

2: Suspendez le thread en appelant wait (). Jusqu'à ce que le thread reçoive notification () ou notifyAll ().

3: La tâche attend la fin d'une entrée / sortie.

4: La tâche tente d'utiliser d'autres méthodes de contrôle de synchronisation sur un objet, mais le verrou d'objet n'est pas disponible car une autre tâche a déjà acquis le verrou.

Lorsque vous interrompez une tâche bloquée, vous devrez peut-être nettoyer les ressources. Pour cette raison, l'interruption au milieu de la méthode run () de la tâche ressemble plus à une exception levée, donc des exceptions sont utilisées dans ce type d'interruption d'exception dans les threads java. Vous devez donc écrire soigneusement des clauses try-catch pour tout nettoyer correctement.

La classe Thread contient la méthode Interrupt () , vous pouvez donc interrompre la tâche bloquée. Cette méthode définira l'état d'interruption du thread. Si un thread est bloqué ou tente d'effectuer une opération de blocage, l' appel de cette méthode à ce moment lèvera une InterruptedException .
Lorsque l'exception est levée ou que la tâche appelle la méthode Thread.interrupt, l'état d'interruption est réinitialisé.
La méthode Thread.interrupt () fournit un deuxième moyen de quitter run () sans lever d'exception. Pour appeler Thread.interrupt (), vous devez contenir un objet Thread.

L'exécuteur fourni par la nouvelle bibliothèque de classes actuelle semble éviter la manipulation directe des objets Thread.
Si shutdownNow () est appelé sur l'Executor , il enverra un appel d'interruption () à tous les threads qu'il démarre .
Cancel (boolean) est un moyen d'interrompre un seul thread démarré par Executor. À ce stade, la tâche doit être lancée par la méthode submit () au lieu de la méthode execute () .
La méthode submit () retournera un Future <?> Générique, sur lequel la méthode cancel (boolean) (paramètre est true) peut être appelée pour terminer la tâche .

class SleepBlocked implements Runnable{
    
    
	public void run() {
    
    
		try {
    
    
			TimeUnit.MILLISECONDS.sleep(100);
		}catch(InterruptedException e) {
    
    
			System.out.println("InterruptedException");
		}
		System.out.println("Exiting SleepBlocked.run()");
	}
} 
class IOBlocked implements Runnable{
    
    
	private InputStream in;
    public IOBlocked(InputStream is) {
    
    in=is;}
	@Override
	public void run() {
    
    
		try {
    
    
			System.out.println("Waiting for read():");
			in.read();
		}catch(IOException e) {
    
    
			if(Thread.currentThread().isInterrupted()) {
    
    
				System.out.println("Interrupted from blocked I/O");
			}
			else {
    
    
				throw new RuntimeException(e);
			}
		}
		System.out.println("Exiting IOBlocked.run()");
	}
}
class SynchronizedBlocked implements Runnable{
    
    
	public synchronized void f() {
    
    
		while(true) {
    
    
			Thread.yield();
		}
	}
	public SynchronizedBlocked() {
    
    
		new Thread() {
    
    
			public void run() {
    
    
				f();
			}
		}.start();
	}
	public void run() {
    
    
		System.out.println("Trying to call f()");
		f();
		System.out.println("Exiting SynchronizedBlocked.run()");
	}
}
public class Interrupting {
    
    
	private static ExecutorService exec=Executors.newCachedThreadPool();
	static void test(Runnable r) throws InterruptedException{
    
    
		Future<?> f=exec.submit(r);
		TimeUnit.MILLISECONDS.sleep(100);
		System.out.println("Interrupting "+r.getClass().getName());
		f.cancel(true);
		System.out.println("Interrupting sent to "+r.getClass().getName());
	}
	public static void main(String[] args) throws InterruptedException {
    
    
		// TODO Auto-generated method stub
        test(new SleepBlocked());
        test(new IOBlocked(System.in));
        test(new SynchronizedBlocked());
        TimeUnit.MILLISECONDS.sleep(3);
        System.out.println("Absorbing with System.exit(0)");
        System.exit(0);
	}

}
/*
Exiting SleepBlocked.run()
Interrupting demo.SleepBlocked
Interrupting sent to demo.SleepBlocked
Waiting for read():
Interrupting demo.IOBlocked
Interrupting sent to demo.IOBlocked
Trying to call f()
Interrupting demo.synchronizedBlocked
Interrupting sent to demo.synchronizedBlocked
Absorbing with System.exit(0)
*/

Chaque tâche du programme ci-dessus représente un type de blocage différent. SleepBlock () est un exemple de blocage interruptible, tandis que IOBlocked et SynchronizedBlocked sont des exemples de blocage non bloquable. Par conséquent, les E / S et l'attente sur le bloc synchronisé sont ininterrompus. La navigation dans le code peut constater que, qu'il s'agisse d'E / S ou d'essayer d'appeler la méthode synchronisée, aucun gestionnaire InterruptedException n'est requis.
Dans SynchronizedBlocked, nous devons d'abord acquérir le verrou, ce qui est obtenu en créant une instance de la classe Thread anonyme, qui appelle f () pour acquérir d'abord le verrou d'objet. Comme la méthode f () est une boucle infinie et ne revient jamais, le verrou ne sera jamais libéré. À ce stade, la méthode Synchronized.run () tente d'acquérir le verrou d'objet et les blocs en attente de libération du verrou.
L'exemple de programme ci-dessus montre que vous ne pouvez pas interrompre un thread qui tente d'acquérir un verrou synchronisé ou qui tente d'effectuer une opération d'E / S.

Méthode de traitement des E / S pour cela

Quant à la classe nio plus conviviale d'E / S d'interruption, nous l'ajouterons lorsque nous aurons terminé l'apprentissage.

class BlockedMutex{
    
    
	private Lock lock=new ReentrantLock();
	public BlockedMutex() {
    
    
		lock.lock();
	}
	public void f() {
    
    
		try {
    
    
			lock.lockInterruptibly();
			System.out.println("lock acquired in f()");
		}catch(InterruptedException e) {
    
    
			System.out.println("Interruppted from lock acquisition in f()");
		}
	}
}
class Blocked2 implements Runnable{
    
    
	BlockedMutex blocked=new BlockedMutex();
	public void run() {
    
    
		System.out.println("Waiting for f() in BlockedMutex");
		blocked.f();
		System.out.println("Broken out of blocked call");
	}
}
public class Interrupting2 {
    
    

	public static void main(String[] args) throws InterruptedException {
    
    
		// TODO Auto-generated method stub
        Thread t=new Thread(new Blocked2());
        t.start();
        TimeUnit.MILLISECONDS.sleep(1);
        System.out.println("Issuing t.interrupt()");
        t.interrupt();
	}

}

Le programme ci-dessus: java SE5 ajoute une fonctionnalité permettant aux tâches bloquées sur ReentrantLock d'être interrompues, ce qui est différent des tâches bloquées dans des méthodes synchronisées ou des sections critiques.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_43916777/article/details/104316678
conseillé
Classement