Vendredi et week-end derniers, j'ai pris une pause dans mon travail chargé et j'ai examiné l'implémentation de Thread.interrupt et LockSupport après Java 5 tout en regardant Java cocurrent.
Avant de présenter, permettez-moi de poser quelques questions.
Quelle est la relation entre la méthode Thread.interrupt() et InterruptedException ? L'exception InterruptedException est-elle déclenchée par une interruption ?
Dans quel état Thread.interrupt() interrompra-t-il le travail du thread ? COURIR ou BLOQUER ?
La programmation générale des Threads doit-elle prêter attention aux interruptions ? Comment y faire face de manière générale ? A quoi peut-il servir ?
Quelle est la différence entre LockSupport.park() et unpark(), et object.wait() et notify() ?
A quoi sert l'objet bloqueur passé par LockSupport.park(Object blocker) ?
LockSupport peut-il répondre aux événements Thread.interrupt() ? L'InterruptedException sera-t-elle levée ?
Existe-t-il une fonction de rappel correspondante pour le traitement Thread.interrupt() ? Quelque chose comme un crochet ?
Si vous pouvez répondre clairement à tout, cela signifie que vous comprenez déjà parfaitement Thread.interrupt et que vous n'avez pas besoin de lire plus loin.
Si vous n’êtes toujours pas clair, réglons-le avec ces questions.
Plusieurs méthodes pour gérer l'interruption de Thread :
public void interrompu() : exécute l'événement d'interruption de thread
public boolean isInterrupted() : Vérifiez si le thread en cours est interrompu
public static boolean interrompu() : vérifiez si le thread actuel est interrompu et réinitialisez les informations d'interruption. Semblable à réinitialiserAndGet()
comprendre:
1. Chaque thread dispose d'un indicateur d'état d'interruption pour indiquer si le thread actuel est dans un état interrompu.
2. Généralement, il existe deux méthodes de traitement lors de l'appel de Thread.interrupt() lorsque vous rencontrez un état de bloc de faible priorité, tel que object.wait(), object.sleep(), object.join(). Cela déclenchera immédiatement un déblocage pour débloquer et lancer une InterruptedException.
Dans d'autres cas, Thread.interrupt() met uniquement à jour l'indicateur d'état. Ensuite, votre thread de travail vérifie via Thread.isInterrrupted() et peut effectuer le traitement correspondant, comme lancer InterruptedException ou effacer le statut, annuler la tâche, etc.
Décrit dans l'interruption javadoc :
meilleures pratiques
Il y a un article sur IBM qui est plutôt bon. Théorie et pratique Java : Dealing with InterruptedException, qui mentionne plusieurs bonnes pratiques pour la gestion des interruptions.
N'avalez pas les interruptions (Ne mangez pas d'interruption, il existe généralement deux types de traitement : continuez à lancer InterruptedException. L'autre consiste à continuer à définir l'indicateur d'exception Thread.interrupt(), permettant au niveau supérieur de le gérer en conséquence.
Copiez le code comme suit :
classe publique TaskRunner implémente Runnable {
file d'attente privée BlockingQueue<Task> ;
public TaskRunner (file d'attente BlockingQueue<Task>) {
this.queue = file d'attente ;
}
public void run() {
essayer {
tandis que (vrai) {
Tâche task = queue.take(10, TimeUnit.SECONDS);
tâche.execute();
}
}
catch (InterruptedException e) {
// Restaure l'état interrompu
Thread.currentThread().interrupt();
}
}
}
Copiez le code comme suit :
classe publique TaskRunner implémente Runnable {
file d'attente privée BlockingQueue<Task> ;
public TaskRunner (file d'attente BlockingQueue<Task>) {
this.queue = file d'attente ;
}
public void run() {
essayer {
tandis que (vrai) {
Tâche task = queue.take(10, TimeUnit.SECONDS);
tâche.execute();
}
}
catch (InterruptedException e) {
// Restaure l'état interrompu
Thread.currentThread().interrupt();
}
}
}
Implémentation de tâches annulables avec Interrupt (utilisez Thread.interrupt() pour concevoir et prendre en charge des tâches pouvant être annulées)
Copiez le code comme suit :
la classe publique PrimeProducer étend le fil {
file d'attente finale privée BlockingQueue<BigInteger> ;
PrimeProducer (file d'attente BlockingQueue<BigInteger>) {
this.queue = file d'attente ;
}
public void run() {
essayer {
BigInteger p = BigInteger.ONE;
tandis que (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consommée) {
/* Autoriser le thread à se fermer */
}
}
public void Cancel() {interruption(); } // Lancer une interruption
}<SPAN style="ESPACE BLANC : normal"> </SPAN>
Copiez le code comme suit :
la classe publique PrimeProducer étend le fil {
file d'attente finale privée BlockingQueue<BigInteger> ;
PrimeProducer (file d'attente BlockingQueue<BigInteger>) {
this.queue = file d'attente ;
}
public void run() {
essayer {
BigInteger p = BigInteger.ONE;
tandis que (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consommée) {
/* Autoriser le thread à se fermer */
}
}
public void Cancel() {interruption(); } // Lancer une interruption
}<SPAN style="ESPACE BLANC : normal"> </SPAN>
Événement de traitement d'interruption de registre (utilisation anormale)
Généralement, les tâches normales sont conçues pour gérer l'annulation, et elles utilisent toutes une interrogation active pour vérifier Thread.isInterrupt(), qui a un certain degré d'intégration dans l'entreprise elle-même, et il y a également un délai pour attendre la suivante. point de contrôle (qui sait quand est le prochain point de contrôle ? Surtout lors de l'exécution d'un socket.read, j'ai rencontré un problème de délai d'attente HttpClient).
Jetons un coup d'œil. L'implémentation du lancement actif d'InterruptedException est basée sur la conception d'InterruptibleChannel, qui est assez intelligente.
Copiez le code comme suit :
interface InterruptAble { // Définir une interface interruption
public void interrompu() lève InterruptedException ;
}
la classe abstraite InterruptSupport implémente InterruptAble {
booléen volatile privé interrompu = faux ;
interrupteur Interruptible privé = new Interruptible() {
interruption publique vide() {
interrompu = vrai ;
InterruptSupport.this.interrupt(); // Position 3
}
} ;
public final boolean perform() lance InterruptedException {
essayer {
bloquéOn (interrupteur); // Position 1
if (Thread.currentThread().isInterrupted()) { // Interrompu immédiatement
interrupteur.interrupt();
}
//Exécuter le code métier
entreprise();
} enfin {
bloquéOn(null); // Position 2
}
retour interrompu ;
}
public abstract void bussiness() ;
interruption publique abstraite nulle ();
// -- sun.misc.SharedSecrets --
static void blockOn (Interruptible intr) { // package-private
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Copiez le code comme suit :
interface InterruptAble { // Définir une interface interruption
public void interrompu() lève InterruptedException ;
}
la classe abstraite InterruptSupport implémente InterruptAble {
booléen volatile privé interrompu = faux ;
interrupteur Interruptible privé = new Interruptible() {
interruption publique vide() {
interrompu = vrai ;
InterruptSupport.this.interrupt(); // Position 3
}
} ;
public final boolean perform() lance InterruptedException {
essayer {
bloquéOn (interrupteur); // Position 1
if (Thread.currentThread().isInterrupted()) { // Interrompu immédiatement
interrupteur.interrupt();
}
//Exécuter le code métier
entreprise();
} enfin {
bloquéOn(null); // Position 2
}
retour interrompu ;
}
public abstract void bussiness() ;
interruption publique abstraite nulle ();
// -- sun.misc.SharedSecrets --
static void blockOn (Interruptible intr) { // package-private
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Description du code, quelques astuces :
Position 1 : utilisez la méthode blockOn fournie par Sun pour lier le hook de traitement d'événement Interruptible correspondant au thread spécifié.
Position 2 : Après avoir exécuté le code, supprimez le hook. Évitez l'impact sur le prochain événement de traitement de thread lors de l'utilisation du pool de connexions.
Position 3 : définit la méthode de traitement du hook d'événement Interruptible et rappelle la méthode InterruptSupport.this.interrupt(). Les sous-classes peuvent intégrer et implémenter leur propre logique métier, telle que la fermeture du flux sock, etc.
utiliser:
Copiez le code comme suit :
la classe InterruptRead étend InterruptSupport {
FileInputStream privé dans ;
@Outrepasser
public void business() {
File file = new File("/dev/urandom"); // Lit le trou noir Linux, ne finit jamais de lire
essayer {
in = nouveau FileInputStream(fichier);
octet[] octets = nouvel octet[1024];
while (in.read(octets, 0, 1024) > 0) {
// Thread.sleep(100);
// if (Thread.interrupted()) {// Méthode de vérification d'interruption précédente
// lance une nouvelle InterruptedException("");
// }
}
} attraper (Exception e) {
lancer une nouvelle RuntimeException(e);
}
}
public FileInputStream getIn() {
rentrer;
}
@Outrepasser
interruption publique vide() {
essayer {
in.getChannel().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main (String args []) lève une exception {
test final InterruptRead = new InterruptRead();
Fil t = nouveau fil() {
@Outrepasser
public void run() {
démarrage long = System.currentTimeMillis();
essayer {
System.out.println("Démarrage d'InterruptRead!");
test.execute();
} catch (InterruptedException e) {
System.out.println("InterruptRead end! cost time : " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
} ;
t.start();
// Laisse Read s'exécuter d'abord pendant 3 secondes
Thread.sleep(3000);
//Émet une interruption
t.interruption();
}
Copiez le code comme suit :
la classe InterruptRead étend InterruptSupport {
FileInputStream privé dans ;
@Outrepasser
public void business() {
File file = new File("/dev/urandom"); // Lit le trou noir Linux, ne finit jamais de lire
essayer {
in = nouveau FileInputStream(fichier);
octet[] octets = nouvel octet[1024];
while (in.read(octets, 0, 1024) > 0) {
// Thread.sleep(100);
// if (Thread.interrupted()) {// Méthode de vérification d'interruption précédente
// lance une nouvelle InterruptedException("");
// }
}
} attraper (Exception e) {
lancer une nouvelle RuntimeException(e);
}
}
public FileInputStream getIn() {
rentrer;
}
@Outrepasser
interruption publique vide() {
essayer {
in.getChannel().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main (String args []) lève une exception {
test final InterruptRead = new InterruptRead();
Fil t = nouveau fil() {
@Outrepasser
public void run() {
démarrage long = System.currentTimeMillis();
essayer {
System.out.println("Démarrage d'InterruptRead!");
test.execute();
} catch (InterruptedException e) {
System.out.println("InterruptRead end! cost time : " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
} ;
t.start();
// Laisse Read s'exécuter d'abord pendant 3 secondes
Thread.sleep(3000);
//Émet une interruption
t.interruption();
}
Introduction au code source du jdk :
1. Le crochet fourni par Sun peut afficher le code correspondant du système, ligne : 1125.
Copiez le code comme suit :
sun.misc.SharedSecrets.setJavaLangAccess(nouveau sun.misc.JavaLangAccess(){
public sun.reflect.ConstantPool getConstantPool (Classe classe) {
return klass.getConstantPool();
}
public void setAnnotationType (classe de classe, type AnnotationType) {
klass.setAnnotationType(type);
}
public AnnotationType getAnnotationType (Classe classe) {
return klass.getAnnotationType();
}
public <E étend Enum<E>>
E[] getEnumConstantsShared(Class<E> classe) {
return klass.getEnumConstantsShared();
}
public void blockOn(Thread t, Interruptible b) {
t.blockedOn(b);
}
});
Copiez le code comme suit :
sun.misc.SharedSecrets.setJavaLangAccess(nouveau sun.misc.JavaLangAccess(){
public sun.reflect.ConstantPool getConstantPool (Classe classe) {
return klass.getConstantPool();
}
public void setAnnotationType (classe de classe, type AnnotationType) {
klass.setAnnotationType(type);
}
public AnnotationType getAnnotationType (Classe classe) {
return klass.getAnnotationType();
}
public <E étend Enum<E>>
E[] getEnumConstantsShared(Class<E> classe) {
return klass.getEnumConstantsShared();
}
public void blockOn(Thread t, Interruptible b) {
t.blockedOn(b);
}
});
2. Thread.interruption()
Copiez le code comme suit :
interruption publique vide() {
si (this != Thread.currentThread())
checkAccess();
synchronisé (blockerLock) {
Interruptible b = bloqueur ;
si (b != nul) {
interrompu0(); // Juste pour définir l'indicateur d'interruption
b.interrupt(); //Hook de rappel
retour;
}
}
interruption0();
}
Copiez le code comme suit :
interruption publique vide() {
si (this != Thread.currentThread())
checkAccess();
synchronisé (blockerLock) {
Interruptible b = bloqueur ;
si (b != nul) {
interrompu0(); // Juste pour définir l'indicateur d'interruption
b.interrupt(); //Hook de rappel
retour;
}
}
interruption0();
}
Pour plus d'informations sur l'utilisation de Thread.stop, suspendre, reprendre et interrompre, vous pouvez consulter la documentation de Sun, telle que http://download.oracle.com/javase/6/docs/technotes/guides/concurrency /threadPrimitiveDeprecation .html
Enfin, répondons à certaines des questions précédentes :
Question 1 : Quelle est la relation entre la méthode Thread.interrupt() et InterruptedException ? L'exception InterruptedException est-elle déclenchée par une interruption ?
Réponse : Thread.interrupt() lancera activement InterruptedException uniquement dans Object.wait(), .Object.join() et Object.sleep(). C'est courant dans d'autres blocs, simplement en définissant une information d'indicateur de Thread, et le programme doit le traiter lui-même.
Copiez le code comme suit :
if (Thread.interrupted()) // Efface l'état interrompu !
lancer une nouvelle InterruptedException();
Copiez le code comme suit :
if (Thread.interrupted()) // Efface l'état interrompu !
lancer une nouvelle InterruptedException();
Question 2 : Dans quel état Thread.interrupt() interrompra-t-il le travail du thread ? COURIR ou BLOQUER ?
Réponse : Le but de la conception Thread.interrupt est principalement de gérer les threads dans un état de bloc, tels que les états wait() et sleep(). Cependant, l'annulation de tâches peut être prise en charge lors de la conception du programme, et l'état RUNNING peut également être pris en charge. Par exemple, Object.join() et certaines conceptions de canaux nio prenant en charge les interruptions.
Question 3 : La programmation générale des Threads doit-elle prêter attention aux interruptions ? Comment y faire face de manière générale ? A quoi peut-il servir ?
Réponse : Interruption d'utilisation : opération de déblocage, prise en charge de l'annulation de tâches, nettoyage des données, etc.
Question 4 : Quelle est la différence entre LockSupport.park() et unpark() et object.wait() et notify() ?
répondre:
1. Les sujets sont différents. LockSuport effectue principalement un traitement de blocage pour Thread. Il peut spécifier l'objet cible de la file d'attente de blocage et spécifier un thread spécifique à réveiller à chaque fois. Object.wait() prend l'objet comme dimension, bloque le thread actuel et réveille un seul (aléatoire) ou tous les threads.
2. Les mécanismes de mise en œuvre sont différents. Bien que LockSuport puisse spécifier l'objet objet du moniteur, les files d'attente de blocage de LockSuport et object.wait() ne se croisent pas. Vous pouvez jeter un oeil à l'exemple de test. object.notifyAll() ne peut pas réveiller le thread bloquant de LockSupport.
Question 5 : A quoi sert l'objet bloqueur passé par LockSupport.park (Object blocker) ?
Réponse : Le blcoker correspondant sera enregistré dans un attribut parkBlocker de Thread. Il est très pratique de surveiller des objets bloquants spécifiques via la commande jstack.
Copiez le code comme suit :
parc vide statique public (bloqueur d'objets) {
Fil t = Thread.currentThread();
setBlocker(t, blocker); //Définir la valeur de la propriété Thread.parkBlocker
unsafe.park(faux, 0L);
setBlocker(t, null); // Efface la valeur de la propriété Thread.parkBlocker
}
Copiez le code comme suit :
parc vide statique public (bloqueur d'objets) {
Fil t = Thread.currentThread();
setBlocker(t, blocker); //Définir la valeur de la propriété Thread.parkBlocker
unsafe.park(faux, 0L);
setBlocker(t, null); // Efface la valeur de la propriété Thread.parkBlocker
}
La description javadoc spécifique de LockSupport est également relativement claire. Vous pouvez la lire ci-dessous :
Question 6 : LockSupport peut-il répondre aux événements Thread.interrupt() ? L'InterruptedException sera-t-elle levée ?
Réponse : Il peut répondre aux événements d’interruption, mais ne lancera pas InterruptedException. Concernant le support de LockSupport pour Thread.interrupte, jetez également un œil à la description dans javadoc :
Code de test associé
Copiez le code comme suit :
paquet com.agapple.cocurrent ;
importer java.io.File ;
importer java.io.FileInputStream ;
importer java.lang.reflect.Field ;
importer java.util.concurrent.TimeUnit ;
importer java.util.concurrent.locks.LockSupport ;
classe publique LockSupportTest {
bloqueur LockSupportTest statique privé = new LockSupportTest();
public static void main (String args []) lève une exception {
lockSupportTest();
parcTest();
interrompreParkTest();
interruptionSleepTest();
interruptionWaitTest();
}
/**
* Après l'objet LockSupport.park, essayez d'obtenir l'objet Thread.blocker et appelez son réveil unique
*
* @throwsException
*/
private static void lockSupportTest() lève une exception {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
public void callback() lève une exception {
// essaye de dormir 5 secondes
System.out.println("bloqueur");
LockSupport.park (bloqueur);
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer "lockSupportTest" ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(150);
synchronisé (bloqueur) {
Champ champ = Thread.class.getDeclaredField("parkBlocker");
field.setAccessible(true);
Objet fBlocker = field.get(t);
System.out.println(blocker == fBlocker);
Thread.sleep(100);
System.out.println("notifyAll");
bloqueur.notifyAll();
}
}
/**
* Si vous essayez d'interrompre un object.wait(), l'InterruptedException correspondante sera levée.
*
* @throws InterruptedException
*/
private static void interrompuWaitTest() lance InterruptedException {
Objet final obj = new Object();
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
public void callback() lève une exception {
// essaye de dormir 5 secondes
obj.wait();
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer "interruptWaitTest" ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
t.interrupt(); // Vérifiez si l'interruption reçoit une réponse pendant le parcage
}
/**
* Si vous essayez d'interrompre un Thread.sleep(), l'InterruptedException correspondante sera levée.
*
* @throws InterruptedException
*/
private static void interrompuSleepTest() lance InterruptedException {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
public void callback() lève une exception {
// essaye de dormir 5 secondes
Thread.sleep(5000);
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer « interruptSleepTest » ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
t.interrupt(); // Vérifiez si l'interruption reçoit une réponse pendant le parcage
}
/**
* Essayez d'interrompre un LockSupport.park(), il y aura une réponse mais aucune exception InterruptedException ne sera levée
*
* @throws InterruptedException
*/
private static void interrompuParkTest() lance InterruptedException {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
rappel public void() {
//Essayez de garer votre propre fil de discussion
LockSupport.parkNanos(bloqueur, TimeUnit.SECONDS.toNanos(5));
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer « interruptParkTest » ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
t.interrupt(); // Vérifiez si l'interruption reçoit une réponse pendant le parcage
}
/**
* Essayez d'interrompre un LockSupport.unPark(), il y aura une réponse
*
* @throws InterruptedException
*/
private static void parkTest() lance InterruptedException {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
rappel public void() {
//Essayez de garer votre propre fil de discussion
LockSupport.park (bloqueur);
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer "parkTest" ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
LockSupport.unpark(t);
t.interruption();
}
fil de discussion statique public doTest (appel final TestCallBack) {
retourner un nouveau fil() {
@Outrepasser
public void run() {
File file = new File("/dev/urandom"); // Lire le trou noir Linux
essayer {
FileInputStream in = new FileInputStream(fichier);
octet[] octets = nouvel octet[1024];
while (in.read(octets, 0, 1024) > 0) {
si (Thread.interrupted()) {
lancer une nouvelle InterruptedException("");
}
System.out.println(octets[0]);
Thread.sleep(100);
démarrage long = System.currentTimeMillis();
call.callback();
System.out.println(call.getName() + " coût de fin de rappel : "
+ (System.currentTimeMillis() - début));
}
} attraper (Exception e) {
e.printStackTrace();
}
}
} ;
}
}
interface TestCallBack {
public void callback() lève une exception ;
public String getName();
}
Copiez le code comme suit :
paquet com.agapple.cocurrent ;
importer java.io.File ;
importer java.io.FileInputStream ;
importer java.lang.reflect.Field ;
importer java.util.concurrent.TimeUnit ;
importer java.util.concurrent.locks.LockSupport ;
classe publique LockSupportTest {
bloqueur LockSupportTest statique privé = new LockSupportTest();
public static void main (String args []) lève une exception {
lockSupportTest();
parcTest();
interrompreParkTest();
interruptionSleepTest();
interruptionWaitTest();
}
/**
* Après l'objet LockSupport.park, essayez d'obtenir l'objet Thread.blocker et appelez son réveil unique
*
* @throwsException
*/
private static void lockSupportTest() lève une exception {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
public void callback() lève une exception {
// essaye de dormir 5 secondes
System.out.println("bloqueur");
LockSupport.park (bloqueur);
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer "lockSupportTest" ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(150);
synchronisé (bloqueur) {
Champ champ = Thread.class.getDeclaredField("parkBlocker");
field.setAccessible(true);
Objet fBlocker = field.get(t);
System.out.println(blocker == fBlocker);
Thread.sleep(100);
System.out.println("notifyAll");
bloqueur.notifyAll();
}
}
/**
* Si vous essayez d'interrompre un object.wait(), l'InterruptedException correspondante sera levée.
*
* @throws InterruptedException
*/
private static void interrompuWaitTest() lance InterruptedException {
Objet final obj = new Object();
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
public void callback() lève une exception {
// essaye de dormir 5 secondes
obj.wait();
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer "interruptWaitTest" ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
t.interrupt(); // Vérifie si l'interruption reçoit une réponse pendant le parcage
}
/**
* Si vous essayez d'interrompre un Thread.sleep(), l'InterruptedException correspondante sera levée.
*
* @throws InterruptedException
*/
private static void interrompuSleepTest() lance InterruptedException {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
public void callback() lève une exception {
// essaye de dormir 5 secondes
Thread.sleep(5000);
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer « interruptSleepTest » ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
t.interrupt(); // Vérifie si l'interruption reçoit une réponse pendant le parcage
}
/**
* Essayez d'interrompre un LockSupport.park(), il y aura une réponse mais aucune exception InterruptedException ne sera levée
*
* @throws InterruptedException
*/
private static void interrompuParkTest() lance InterruptedException {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
rappel public void() {
//Essayez de garer votre propre fil de discussion
LockSupport.parkNanos(bloqueur, TimeUnit.SECONDS.toNanos(5));
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer « interruptParkTest » ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
t.interrupt(); // Vérifiez si l'interruption reçoit une réponse pendant le parcage
}
/**
* Essayez d'interrompre un LockSupport.unPark(), il y aura une réponse
*
* @throws InterruptedException
*/
private static void parkTest() lance InterruptedException {
Sujet t = doTest(nouveau TestCallBack() {
@Outrepasser
rappel public void() {
//Essayez de garer votre propre fil de discussion
LockSupport.park (bloqueur);
System.out.println("réveillez-vous maintenant !");
}
@Outrepasser
chaîne publique getName() {
renvoyer "parkTest" ;
}
});
t.start(); // Démarre le fil de lecture
Thread.sleep(2000);
LockSupport.unpark(t);
t.interruption();
}
fil de discussion statique public doTest (appel final TestCallBack) {
retourner un nouveau fil() {
@Outrepasser
public void run() {
File file = new File("/dev/urandom"); // Lire le trou noir Linux
essayer {
FileInputStream in = new FileInputStream(fichier);
octet[] octets = nouvel octet[1024];
while (in.read(octets, 0, 1024) > 0) {
si (Thread.interrupted()) {
lancer une nouvelle InterruptedException("");
}
System.out.println(octets[0]);
Thread.sleep(100);
démarrage long = System.currentTimeMillis();
call.callback();
System.out.println(call.getName() + " coût de fin de rappel : "
+ (System.currentTimeMillis() - début));
}
} attraper (Exception e) {
e.printStackTrace();
}
}
} ;
}
}
interface TestCallBack {
public void callback() lève une exception ;
public String getName();
}
Finalement , j'ai trouvé que l'article devenait de plus en plus long, alors je l'ai simplement posté sur le forum pour que tout le monde puisse en discuter ensemble. Après tout, l'article ne décrivait que quelques éléments liés à l'utilisation et n'introduisait pas Thread depuis le fonctionnement. système ou implémentation native du soleil. Pour certains mécanismes, les Daniumen qui connaissent ce domaine peuvent également exprimer leur avis.