El viernes y fin de semana pasado, me tomé un descanso de mi ajetreado trabajo y revisé la implementación de Thread.interrupt y LockSupport después de Java 5 mientras miraba Java en paralelo.
Antes de presentarme, permítanme hacer algunas preguntas.
¿Cuál es la relación entre el método Thread.interrupt() y InterruptedException? ¿La excepción InterruptedException se desencadena por una interrupción?
¿En qué estado Thread.interrupt() interrumpirá el trabajo del hilo? ¿EJECUTANDO o BLOQUEANDO?
¿La programación general de Thread debe prestar atención a las interrupciones? ¿Cómo afrontarlo en general? ¿Para qué se puede utilizar?
¿Cuál es la diferencia entre LockSupport.park() y unpark(), y object.wait() y notify()?
¿Cuál es el uso del objeto bloqueador pasado por LockSupport.park (bloqueador de objetos)?
¿Puede LockSupport responder a los eventos Thread.interrupt()? ¿Se lanzará InterruptedException?
¿Existe una función de devolución de llamada correspondiente para el procesamiento de Thread.interrupt()? ¿Algo así como una llamada de gancho?
Si puede responder todo con claridad, significa que ya comprende completamente Thread.interrupt y no necesita seguir leyendo.
Si aún no lo tienes claro, solucionémoslo junto con estas preguntas.
Varios métodos para manejar la interrupción de Thread:
interrupción pública vacía (): ejecuta el evento de interrupción del hilo
public boolean isInterrupted(): comprueba si el hilo actual está interrumpido
público estático booleano interrumpido (): comprueba si el hilo actual está interrumpido y restablece la información de interrupción. Similar a resetAndGet()
entender:
1. Cada subproceso tiene un indicador de estado de interrupción para indicar si el subproceso actual está en un estado de interrupción.
2. Generalmente, existen dos métodos de procesamiento al llamar a Thread.interrupt() cuando se encuentra un estado de bloque de baja prioridad, como object.wait(), object.sleep(), object.join(). Inmediatamente activará un desbloqueo para desbloquear y generará una InterruptedException.
En otros casos, Thread.interrupt() solo actualiza el indicador de estado. Luego, su subproceso de trabajo verifica a través de Thread.isInterrrupted() y puede realizar el procesamiento correspondiente, como lanzar InterruptedException o borrar el estado, cancelar la tarea, etc.
Descrito en javadoc de interrupción:
mejores practicas
Hay un artículo sobre IBM que es bastante bueno. Teoría y práctica de Java: cómo lidiar con InterruptedException, que menciona varias de las mejores prácticas para el manejo de interrupciones.
No se trague las interrupciones (no coma las interrupciones, generalmente hay dos tipos de procesamiento: continúe lanzando InterruptedException. El otro es continuar configurando el indicador de excepción Thread.interupt () para permitir que el nivel superior lo maneje en consecuencia.
Copie el código de código de la siguiente manera:
La clase pública TaskRunner implementa Runnable {
cola privada BlockingQueue<Tarea>;
TaskRunner público (cola BlockingQueue<Tarea>) {
this.queue = cola;
}
ejecución pública vacía() {
intentar {
mientras (verdadero) {
Tarea tarea = cola.take(10, TimeUnit.SECONDS);
tarea.ejecutar();
}
}
atrapar (Excepción interrumpida e) {
//Restaurar el estado interrumpido
Thread.currentThread().interrupt();
}
}
}
Copie el código de código de la siguiente manera:
La clase pública TaskRunner implementa Runnable {
cola privada BlockingQueue<Tarea>;
TaskRunner público (cola BlockingQueue<Tarea>) {
this.queue = cola;
}
ejecución pública vacía() {
intentar {
mientras (verdadero) {
Tarea tarea = cola.take(10, TimeUnit.SECONDS);
tarea.ejecutar();
}
}
atrapar (Excepción interrumpida e) {
//Restaurar el estado interrumpido
Thread.currentThread().interrupt();
}
}
}
Implementar tareas cancelables con Interrupt (use Thread.interrupt() para diseñar y respaldar tareas que se pueden cancelar)
Copie el código de código de la siguiente manera:
clase pública PrimeProducer extiende Thread {
cola BlockingQueue<BigInteger> final privada;
PrimeProducer(colaBlockingQueue<BigInteger>) {
this.queue = cola;
}
ejecución pública vacía() {
intentar {
BigInteger p = BigInteger.ONE;
mientras (!Thread.currentThread().isInterrupted())
cola.put(p = p.nextProbablePrime());
} captura (Excepción interrumpida consumida) {
/* Permitir que el hilo salga */
}
}
public void cancel() { interrupción() } // Iniciar una interrupción
}<SPAN estilo="ESPACIO EN BLANCO: normal"> </SPAN>
Copie el código de código de la siguiente manera:
clase pública PrimeProducer extiende Thread {
cola BlockingQueue<BigInteger> final privada;
PrimeProducer(colaBlockingQueue<BigInteger>) {
this.queue = cola;
}
ejecución pública vacía() {
intentar {
BigInteger p = BigInteger.ONE;
mientras (!Thread.currentThread().isInterrupted())
cola.put(p = p.nextProbablePrime());
} captura (Excepción interrumpida consumida) {
/* Permitir que el hilo salga */
}
}
public void cancel() { interrupción() } // Iniciar una interrupción
}<SPAN estilo="ESPACIO EN BLANCO: normal"> </SPAN>
Registrar evento de procesamiento de interrupción (uso anormal)
Generalmente, las tareas normales están diseñadas para manejar la cancelación y todas utilizan sondeo activo para verificar Thread.isInterrupt (), que tiene un cierto grado de integración en el negocio en sí y también hay un retraso. punto de control (quién sabe ¿Cuándo es el próximo punto de control? Especialmente al realizar un socket.read, encontré un problema de tiempo de espera de HttpClient).
Echemos un vistazo. La implementación de lanzar activamente InterruptedException se basa en el diseño de InterruptibleChannel, que es bastante inteligente.
Copie el código de código de la siguiente manera:
interface InterruptAble { // Definir una interfaz interrumpible
interrupción pública nula () lanza InterruptedException;
}
la clase abstracta InterruptSupport implementa InterruptAble {
booleano volátil privado interrumpido = falso;
interruptor interrumpible privado = nuevo interrumpible() {
interrupción pública nula() {
interrumpido = verdadero;
InterruptSupport.this.interrupt() // Posición 3
}
};
La ejecución booleana final pública () lanza InterruptedException {
intentar {
bloqueadoEn(interruptor); // Posición 1
if (Thread.currentThread().isInterrupted()) { // Interrumpido inmediatamente
interruptor.interrupt();
}
//Ejecutar código comercial
negocio();
} finalmente {
bloqueadoEn(nulo); // Posición 2
}
regreso interrumpido;
}
negocio vacío abstracto público();
interrupción nula abstracta pública();
// -- sun.misc.SharedSecrets --
vacío estático bloqueado en (interruptible intr) { // paquete privado
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Copie el código de código de la siguiente manera:
interface InterruptAble { // Definir una interfaz interrumpible
interrupción pública nula () lanza InterruptedException;
}
la clase abstracta InterruptSupport implementa InterruptAble {
booleano volátil privado interrumpido = falso;
interruptor interrumpible privado = nuevo interrumpible() {
interrupción pública nula() {
interrumpido = verdadero;
InterruptSupport.this.interrupt() // Posición 3
}
};
La ejecución booleana final pública () lanza InterruptedException {
intentar {
bloqueadoEn(interruptor); // Posición 1
if (Thread.currentThread().isInterrupted()) { // Interrumpido inmediatamente
interruptor.interrupt();
}
//Ejecutar código comercial
negocio();
} finalmente {
bloqueadoEn(nulo); // Posición 2
}
regreso interrumpido;
}
negocio vacío abstracto público();
interrupción nula abstracta pública();
// -- sun.misc.SharedSecrets --
vacío estático bloqueado en (interruptible intr) { // paquete privado
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Descripción del código, algunos trucos:
Posición 1: utilice el método blockOn proporcionado por Sun para vincular el gancho de procesamiento de eventos interrumpibles correspondiente al subproceso especificado.
Posición 2: después de ejecutar el código, borre el gancho. Evite el impacto en el próximo evento de procesamiento de subprocesos cuando utilice el grupo de conexiones.
Posición 3: define el método de procesamiento del enlace de evento interrumpible y devuelve la llamada al método InterruptSupport.this.interrupt(). Las subclases pueden integrar e implementar su propia lógica de negocios, como el cierre del flujo de calcetines, etc.
usar:
Copie el código de código de la siguiente manera:
clase InterruptRead extiende InterruptSupport {
FileInputStream privado en;
@Anular
negocio público vacío() {
File file = new File("/dev/urandom"); // Lee el agujero negro de Linux, nunca termines de leer
intentar {
en = nuevo FileInputStream(archivo);
byte[] bytes = nuevo byte[1024];
mientras (en.lectura(bytes, 0, 1024) > 0) {
// Thread.sleep(100);
// if (Thread.interrupted()) {// Método de verificación de interrupción anterior
// lanza una nueva excepción interrumpida ("");
// }
}
} captura (Excepción e) {
lanzar nueva RuntimeException(e);
}
}
getIn público FileInputStream() {
regresar en;
}
@Anular
interrupción pública nula() {
intentar {
in.getChannel().close();
} captura (IOException e) {
e.printStackTrace();
}
}
}
public static void main (String args []) lanza una excepción {
prueba final de InterruptRead = nueva InterruptRead();
Hilo t = nuevo hilo() {
@Anular
ejecución pública vacía() {
inicio largo = System.currentTimeMillis();
intentar {
System.out.println("¡Inicio de lectura interrumpida!");
prueba.execute();
} captura (Excepción interrumpida e) {
System.out.println("InterruptRead fin! tiempo de costo: " + (System.currentTimeMillis() - inicio));
e.printStackTrace();
}
}
};
t.start();
// Deja que Read se ejecute primero durante 3 segundos
Hilo.dormir(3000);
//Emitir una interrupción
t.interrupt();
}
Copie el código de código de la siguiente manera:
clase InterruptRead extiende InterruptSupport {
FileInputStream privado en;
@Anular
negocio público vacío() {
File file = new File("/dev/urandom"); // Lee el agujero negro de Linux, nunca termines de leer
intentar {
en = nuevo FileInputStream(archivo);
byte[] bytes = nuevo byte[1024];
mientras (en.lectura(bytes, 0, 1024) > 0) {
// Thread.sleep(100);
// if (Thread.interrupted()) {// Método de verificación de interrupción anterior
// lanza una nueva excepción interrumpida ("");
// }
}
} captura (Excepción e) {
lanzar nueva RuntimeException(e);
}
}
getIn público FileInputStream() {
regresar en;
}
@Anular
interrupción pública nula() {
intentar {
in.getChannel().close();
} captura (IOException e) {
e.printStackTrace();
}
}
}
public static void main (String args []) lanza una excepción {
prueba final de InterruptRead = nueva InterruptRead();
Hilo t = nuevo hilo() {
@Anular
ejecución pública vacía() {
inicio largo = System.currentTimeMillis();
intentar {
System.out.println("¡Inicio de lectura interrumpida!");
prueba.execute();
} captura (Excepción interrumpida e) {
System.out.println("InterruptRead fin! tiempo de costo: " + (System.currentTimeMillis() - inicio));
e.printStackTrace();
}
}
};
t.start();
// Deja que Read se ejecute primero durante 3 segundos
Hilo.dormir(3000);
//Emitir una interrupción
t.interrupt();
}
Introducción al código fuente jdk:
1. El gancho proporcionado por Sun puede ver el código relevante del Sistema, línea: 1125
Copie el código de código de la siguiente manera:
sun.misc.SharedSecrets.setJavaLangAccess(nuevo sun.misc.JavaLangAccess(){
público sun.reflect.ConstantPool getConstantPool (clase de clase) {
devolver klass.getConstantPool();
}
setAnnotationType público vacío (clase de clase, tipo AnnotationType) {
klass.setAnnotationType(tipo);
}
tipo de anotación pública getAnnotationType (clase de clase) {
devolver klass.getAnnotationType();
}
público <E extiende Enum<E>>
E[] getEnumConstantsShared(Clase<E> clase) {
devolver klass.getEnumConstantsShared();
}
vacío público bloqueado en (hilo t, interrumpible b) {
t.bloqueadoEn(b);
}
});
Copie el código de código de la siguiente manera:
sun.misc.SharedSecrets.setJavaLangAccess(nuevo sun.misc.JavaLangAccess(){
público sun.reflect.ConstantPool getConstantPool (clase de clase) {
devolver klass.getConstantPool();
}
setAnnotationType público vacío (clase de clase, tipo AnnotationType) {
klass.setAnnotationType(tipo);
}
tipo de anotación pública getAnnotationType (clase de clase) {
devolver klass.getAnnotationType();
}
público <E extiende Enum<E>>
E[] getEnumConstantsShared(Clase<E> clase) {
devolver klass.getEnumConstantsShared();
}
vacío público bloqueado en (hilo t, interrumpible b) {
t.bloqueadoEn(b);
}
});
2. Hilo.interrupt()
Copie el código de código de la siguiente manera:
interrupción pública nula() {
si (esto! = Thread.currentThread())
comprobarAcceso();
sincronizado (blockerLock) {
Interrumpible b = bloqueador;
si (b! = nulo) {
interrupción0(); // Sólo para establecer el indicador de interrupción
b.interrupt(); //Enganche de devolución de llamada
devolver;
}
}
interrupción0();
}
Copie el código de código de la siguiente manera:
interrupción pública nula() {
si (esto! = Thread.currentThread())
comprobarAcceso();
sincronizado (blockerLock) {
Interrumpible b = bloqueador;
si (b! = nulo) {
interrupción0(); // Sólo para establecer el indicador de interrupción
b.interrupt(); //Enganche de devolución de llamada
devolver;
}
}
interrupción0();
}
Para obtener más información sobre el uso de Thread.stop, suspender, reanudar e interrumpir, puede consultar la documentación de Sun, como http://download.oracle.com/javase/6/docs/technotes/guides/concurrency /threadPrimitiveDeprecation .html
Finalmente, respondamos algunas de las preguntas anteriores:
Pregunta 1: ¿Cuál es la relación entre el método Thread.interrupt() y InterruptedException? ¿La excepción InterruptedException se desencadena por una interrupción?
Respuesta: Thread.interrupt() lanzará activamente InterruptedException solo en Object.wait(), .Object.join() y Object.sleep(). Es común en otros bloques, simplemente configurando la información de un indicador de Thread, el programa necesita procesarlo por sí mismo.
Copie el código de código de la siguiente manera:
if (Thread.interrupted()) // ¡Borra el estado interrumpido!
lanzar una nueva excepción interrumpida();
Copie el código de código de la siguiente manera:
if (Thread.interrupted()) // ¡Borra el estado interrumpido!
lanzar una nueva excepción interrumpida();
Pregunta 2: ¿En qué estado Thread.interrupt() interrumpirá el trabajo del hilo? ¿EJECUTANDO o BLOQUEANDO?
Respuesta: El propósito del diseño Thread.interrupt es principalmente manejar subprocesos en estado de bloque, como los estados de espera () y suspensión (). Sin embargo, la cancelación de tareas se puede admitir durante el diseño del programa y también se puede admitir el estado EN EJECUCIÓN. Por ejemplo, Object.join() y algunos diseños de canales nio que admiten interrupciones.
Pregunta 3: ¿La programación general de subprocesos debe prestar atención a las interrupciones? ¿Cómo afrontarlo en general? ¿Para qué se puede utilizar?
Respuesta: Uso de interrupción: operación de desbloqueo, admite cancelación de tareas, limpieza de datos, etc.
Pregunta 4: ¿Cuál es la diferencia entre LockSupport.park() y unpark() y object.wait() y notify()?
respuesta:
1. Los temas son diferentes. LockSuport realiza principalmente el procesamiento de bloqueo para Thread. Puede especificar el objeto de destino de la cola de bloqueo y especificar un hilo específico para activar cada vez. Object.wait() toma el objeto como dimensión, bloquea el hilo actual y activa uno solo (aleatorio) o todos los hilos.
2. Los mecanismos de implementación son diferentes. Aunque LockSuport puede especificar el objeto del monitor, las colas de bloqueo de LockSuport y object.wait () no se cruzan. Puedes echar un vistazo al ejemplo de prueba. object.notifyAll() no puede activar el hilo de bloqueo de LockSupport.
Pregunta 5: ¿Cuál es el uso del objeto bloqueador pasado por LockSupport.park (bloqueador de objetos)?
Respuesta: El blcoker correspondiente se registrará en un atributo parkBlocker de Thread. Es muy conveniente monitorear objetos de bloqueo específicos a través del comando jstack.
Copie el código de código de la siguiente manera:
parque público de vacío estático (bloqueador de objetos) {
Hilo t = Thread.currentThread();
setBlocker(t, blocker); //Establece el valor de la propiedad Thread.parkBlocker
parque.inseguro(falso, 0L);
setBlocker(t, null); // Borra el valor de la propiedad Thread.parkBlocker
}
Copie el código de código de la siguiente manera:
parque público de vacío estático (bloqueador de objetos) {
Hilo t = Thread.currentThread();
setBlocker(t, blocker); //Establece el valor de la propiedad Thread.parkBlocker
parque.inseguro(falso, 0L);
setBlocker(t, null); // Borra el valor de la propiedad Thread.parkBlocker
}
La descripción javadoc específica de LockSupport también es relativamente clara. Puede leerla a continuación:
Pregunta 6: ¿Puede LockSupport responder a los eventos Thread.interrupt()? ¿Se lanzará InterruptedException?
Respuesta: Puede responder a eventos de interrupción, pero no generará InterruptedException. Con respecto al soporte de LockSupport para Thread.interrupte, consulte también la descripción en javadoc:
Código de prueba relacionado
Copie el código de código de la siguiente manera:
paquete com.agapple.cocurrent;
importar java.io.File;
importar java.io.FileInputStream;
importar java.lang.reflect.Field;
importar java.util.concurrent.TimeUnit;
importar java.util.concurrent.locks.LockSupport;
clase pública LockSupportTest {
bloqueador privado estático LockSupportTest = nuevo LockSupportTest();
public static void main (String args []) lanza una excepción {
lockSupportTest();
pruebadeparque();
interrumpirParkTest();
interrumpirPruebaDormir();
interrupciónPruebadeEspera();
}
/**
* Después del objeto LockSupport.park, intente obtener el objeto Thread.blocker y llame a su activación única
*
* @throwsException
*/
lockSupportTest vacío estático privado () lanza una excepción {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada pública nula () lanza una excepción {
// intenta dormir 5 segundos
System.out.println("bloqueador");
LockSupport.park(bloqueador);
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "lockSupportTest";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.dormir(150);
sincronizado (bloqueador) {
Campo campo = Thread.class.getDeclaredField("parkBlocker");
campo.setAccessible(verdadero);
Objeto fBlocker = field.get(t);
System.out.println(bloqueador == fBlocker);
Hilo.dormir(100);
System.out.println("notificar a todos");
bloqueador.notifyAll();
}
}
/**
* Si intenta interrumpir un objeto.wait(), se generará la InterruptedException correspondiente.
*
* @throws InterruptedException
*/
interrupción estática vacía privadaWaitTest () lanza InterruptedException {
objeto final obj = nuevo objeto();
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada pública nula () lanza una excepción {
// intenta dormir 5 segundos
obj.espera();
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "interruptWaitTest";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
t.interrupt(); // Comprobar si se responde a la interrupción durante el estacionamiento
}
/**
* Si intenta interrumpir Thread.sleep(), se generará la InterruptedException correspondiente.
*
* @throws InterruptedException
*/
InterruptSleepTest vacío estático privado () lanza InterruptedException {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada pública nula () lanza una excepción {
// intenta dormir 5 segundos
Hilo.sleep(5000);
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "interrumpirPruebaSleep";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
t.interrupt(); // Comprobar si se responde a la interrupción durante el estacionamiento
}
/**
* Intente interrumpir LockSupport.park(), habrá una respuesta pero no se generará ninguna excepción InterruptedException
*
* @throws InterruptedException
*/
InterruptParkTest vacío estático privado () lanza InterruptedException {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada nula pública () {
//Intenta aparcar tu propio hilo
LockSupport.parkNanos(bloqueador, TimeUnit.SECONDS.toNanos(5));
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "interruptParkTest";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
t.interrupt(); // Comprobar si se responde a la interrupción durante el estacionamiento
}
/**
* Intente interrumpir LockSupport.unPark(), habrá una respuesta
*
* @throws InterruptedException
*/
parkTest vacío estático privado() lanza InterruptedException {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada nula pública () {
//Intenta aparcar tu propio hilo
LockSupport.park(bloqueador);
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "prueba de parque";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
LockSupport.unpark(t);
t.interrupt();
}
Hilo estático público doTest (llamada final TestCallBack) {
devolver nuevo hilo() {
@Anular
ejecución pública vacía() {
Archivo archivo = nuevo Archivo("/dev/urandom"); // Leer el agujero negro de Linux
intentar {
FileInputStream en = nuevo FileInputStream(archivo);
byte[] bytes = nuevo byte[1024];
mientras (en.lectura(bytes, 0, 1024) > 0) {
si (Thread.interrupted()) {
lanzar una nueva excepción interrumpida ("");
}
System.out.println(bytes[0]);
Hilo.dormir(100);
inicio largo = System.currentTimeMillis();
call.callback();
System.out.println(call.getName() + "coste de finalización de la devolución de llamada:"
+ (System.currentTimeMillis() - inicio));
}
} captura (Excepción e) {
e.printStackTrace();
}
}
};
}
}
interfaz TestCallBack {
devolución de llamada pública nula () lanza una excepción;
cadena pública getName();
}
Copie el código de código de la siguiente manera:
paquete com.agapple.cocurrent;
importar java.io.File;
importar java.io.FileInputStream;
importar java.lang.reflect.Field;
importar java.util.concurrent.TimeUnit;
importar java.util.concurrent.locks.LockSupport;
clase pública LockSupportTest {
bloqueador privado estático LockSupportTest = nuevo LockSupportTest();
public static void main (String args []) lanza una excepción {
lockSupportTest();
pruebadeparque();
interrumpirParkTest();
interrumpirPruebaDormir();
interrupciónPruebadeEspera();
}
/**
* Después del objeto LockSupport.park, intente obtener el objeto Thread.blocker y llame a su activación única
*
* @throwsException
*/
lockSupportTest vacío estático privado () lanza una excepción {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada pública nula () lanza una excepción {
// intenta dormir 5 segundos
System.out.println("bloqueador");
LockSupport.park(bloqueador);
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "lockSupportTest";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.dormir(150);
sincronizado (bloqueador) {
Campo campo = Thread.class.getDeclaredField("parkBlocker");
campo.setAccessible(verdadero);
Objeto fBlocker = field.get(t);
System.out.println(bloqueador == fBlocker);
Hilo.dormir(100);
System.out.println("notificar a todos");
bloqueador.notifyAll();
}
}
/**
* Si intenta interrumpir un objeto.wait(), se generará la InterruptedException correspondiente.
*
* @throws InterruptedException
*/
interrupción estática vacía privadaWaitTest () lanza InterruptedException {
objeto final obj = nuevo objeto();
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada pública nula () lanza una excepción {
// intenta dormir 5 segundos
obj.espera();
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "prueba de espera de interrupción";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
t.interrupt(); // Comprobar si se responde a la interrupción durante el estacionamiento
}
/**
* Si intenta interrumpir Thread.sleep(), se generará la InterruptedException correspondiente.
*
* @throws InterruptedException
*/
void estático privado interruptSleepTest() lanza InterruptedException {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada pública nula () lanza una excepción {
// intenta dormir 5 segundos
Hilo.sleep(5000);
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "interrumpirPruebaSleep";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
t.interrupt(); // Comprobar si se responde a la interrupción durante el estacionamiento
}
/**
* Intente interrumpir LockSupport.park(), habrá una respuesta pero no se generará ninguna excepción InterruptedException
*
* @throws InterruptedException
*/
InterruptParkTest vacío estático privado () lanza InterruptedException {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada nula pública () {
//Intenta aparcar tu propio hilo
LockSupport.parkNanos(bloqueador, TimeUnit.SECONDS.toNanos(5));
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "interruptParkTest";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
t.interrupt(); // Comprobar si se responde a la interrupción durante el estacionamiento
}
/**
* Intente interrumpir LockSupport.unPark(), habrá una respuesta
*
* @throws Excepción interrumpida
*/
parkTest vacío estático privado() lanza InterruptedException {
Hilo t = doTest(nuevo TestCallBack() {
@Anular
devolución de llamada nula pública () {
//Intenta aparcar tu propio hilo
LockSupport.park(bloqueador);
System.out.println("¡despierta ahora!");
}
@Anular
cadena pública getName() {
devolver "prueba de parque";
}
});
t.start(); // Iniciar el hilo de lectura
Hilo.sleep(2000);
LockSupport.unpark(t);
t.interrupt();
}
Hilo estático público doTest (llamada final TestCallBack) {
devolver nuevo hilo() {
@Anular
ejecución pública vacía() {
Archivo archivo = nuevo Archivo("/dev/urandom"); // Leer el agujero negro de Linux
intentar {
FileInputStream en = nuevo FileInputStream(archivo);
byte[] bytes = nuevo byte[1024];
mientras (en.lectura(bytes, 0, 1024) > 0) {
si (Thread.interrupted()) {
lanzar una nueva excepción interrumpida ("");
}
System.out.println(bytes[0]);
Hilo.dormir(100);
inicio largo = System.currentTimeMillis();
call.callback();
System.out.println(call.getName() + "coste de finalización de la devolución de llamada:"
+ (System.currentTimeMillis() - inicio));
}
} captura (Excepción e) {
e.printStackTrace();
}
}
};
}
}
interfaz TestCallBack {
devolución de llamada pública nula () lanza una excepción;
cadena pública getName();
}
Finalmente <BR>descubrí que el artículo se hacía cada vez más largo, así que simplemente lo publiqué en el foro para que todos lo discutieran juntos. Después de todo, el artículo solo describía algunas cosas a nivel de uso y no presentaba Thread desde el punto de vista operativo. Sistema o implementación nativa de Sun Para algunos mecanismos, los Daniumen que están familiarizados con esta área también pueden expresar sus opiniones.