Na última sexta-feira e fim de semana, fiz uma pausa em meu trabalho ocupado e revisei a implementação de Thread.interrupt e LockSupport após Java 5 enquanto observava Java cocorrente.
Antes de apresentar, deixe-me fazer algumas perguntas.
Qual é a relação entre o método Thread.interrupt() e InterruptedException? A exceção InterruptedException é acionada por interrupção?
Em que estado Thread.interrupt() interromperá o trabalho do thread? EXECUTANDO ou BLOQUEANDO?
A programação geral do Thread precisa prestar atenção às interrupções? Como lidar com isso em geral? Para que pode ser usado?
Qual é a diferença entre LockSupport.park() e unpark() e object.wait() e notify()?
Qual é a utilidade do objeto bloqueador passado por LockSupport.park (objeto bloqueador)?
O LockSupport pode responder a eventos Thread.interrupt()? Será InterruptedException lançada?
Existe uma função de retorno de chamada correspondente para processamento Thread.interrupt()? Algo como uma chamada no gancho?
Se você puder responder tudo com clareza, significa que você já entende totalmente Thread.interrupt e não precisa ler mais.
Se você ainda não está claro, vamos resolver isso junto com essas questões.
Vários métodos para lidar com a interrupção do Thread:
public void interrupção(): executa evento de interrupção de thread
public boolean isInterrupted(): verifica se o thread atual está interrompido
public static boolean interrompido(): verifica se o thread atual está interrompido e redefine as informações de interrupção. Semelhante a resetAndGet()
entender:
1. Cada thread possui um sinalizador de status de interrupção para indicar se o thread atual está em um estado interrompido.
2. Geralmente, existem dois métodos de processamento ao chamar Thread.interrupt() ao encontrar um estado de bloco de baixa prioridade, como object.wait(), object.sleep(), object.join(). Isso irá acionar imediatamente um desbloqueio para desbloquear e lançar uma InterruptedException.
Em outros casos, Thread.interrupt() apenas atualiza o sinalizador de status. Em seguida, seu thread de trabalho verifica Thread.isInterrrupted() e pode executar o processamento correspondente, como lançar InterruptedException ou limpar o status, cancelar a tarefa, etc.
Descrito na interrupção javadoc:
melhores práticas
Há um artigo sobre a IBM que é muito bom. Teoria e prática Java: Lidando com InterruptedException, que menciona várias práticas recomendadas para tratamento de interrupções.
Não engula interrupções (não coma interrupção, geralmente existem dois tipos de processamento: continue a lançar InterruptedException. O outro é continuar a definir o sinalizador de exceção Thread.interupt(), permitindo que o nível superior trate-o adequadamente.
Copie o código do código da seguinte forma:
classe pública TaskRunner implementa Runnable {
fila privada BlockingQueue<Task>;
public TaskRunner(BlockingQueue<Task> fila) {
this.queue = fila;
}
execução nula pública() {
tentar {
enquanto (verdadeiro) {
Tarefa tarefa = queue.take(10, TimeUnit.SECONDS);
tarefa.execute();
}
}
catch(InterruptedExceptione){
//Restaura o status interrompido
Thread.currentThread().interrupt();
}
}
}
Copie o código do código da seguinte forma:
classe pública TaskRunner implementa Runnable {
fila privada BlockingQueue<Task>;
public TaskRunner(BlockingQueue<Task> fila) {
this.queue = fila;
}
execução nula pública() {
tentar {
enquanto (verdadeiro) {
Tarefa tarefa = queue.take(10, TimeUnit.SECONDS);
tarefa.execute();
}
}
catch(InterruptedException e){
//Restaura o status interrompido
Thread.currentThread().interrupt();
}
}
}
Implementando tarefas canceláveis com Interrupt (use Thread.interrupt() para projetar e dar suporte a tarefas que podem ser canceladas)
Copie o código do código da seguinte forma:
classe pública PrimeProducer estende Thread {
fila final privada BlockingQueue<BigInteger>;
PrimeProducer(BlockingQueue<BigInteger> fila) {
this.queue = fila;
}
execução nula pública() {
tentar {
BigInteger p = BigInteger.ONE;
enquanto (!Thread.currentThread().isInterrupted())
fila.put(p = p.nextProbablePrime());
} catch (InterruptedException consumida) {
/* Permitir que o thread saia */
}
}
public void cancel() {interrupt() } // Inicia uma interrupção
}<SPAN style="WHITE-SPACE: normal"> </SPAN>
Copie o código do código da seguinte forma:
classe pública PrimeProducer estende Thread {
fila final privada BlockingQueue<BigInteger>;
PrimeProducer(BlockingQueue<BigInteger> fila) {
this.queue = fila;
}
execução nula pública() {
tentar {
BigInteger p = BigInteger.ONE;
enquanto (!Thread.currentThread().isInterrupted())
fila.put(p = p.nextProbablePrime());
} catch (InterruptedException consumida) {
/* Permitir que o thread saia */
}
}
public void cancel() {interrupt() } // Inicia uma interrupção
}<SPAN style="WHITE-SPACE: normal"> </SPAN>
Registrar evento de processamento de interrupção (uso anormal)
Geralmente, as tarefas normais são projetadas para lidar com o cancelamento e todas usam sondagem ativa para verificar Thread.isInterrupt(), que tem um certo grau de integração no próprio negócio e também há um atraso. ponto de verificação (quem sabe quando é o próximo ponto de verificação? Especialmente ao executar um socket.read, encontrei um problema de tempo limite do HttpClient).
Vamos dar uma olhada. A implementação do lançamento ativo de InterruptedException é baseada no design de InterruptibleChannel, que é bastante inteligente.
Copie o código do código da seguinte forma:
interface InterruptAble { // Define uma interface interrompível
public void interrupção() lança InterruptedException;
}
classe abstrata InterruptSupport implementa InterruptAble {
privado volátil booleano interrompido = falso;
interruptor interrompível privado = new Interruptível() {
interrupção nula pública() {
interrompido = verdadeiro;
InterruptSupport.this.interrupt(); // Posição 3
}
};
public final boolean execute() lança InterruptedException {
tentar {
bloqueadoOn(interruptor); // Posição 1
if (Thread.currentThread().isInterrupted()) { // Interrompido imediatamente
interruptor.interrupt();
}
//Executa o código comercial
negócio();
} finalmente {
bloqueadoOn(null); // Posição 2
}
retorno interrompido;
}
público abstrato void bussiness() ;
público abstrato void interrupção();
// -- sun.misc.SharedSecrets --
static void bloqueadoOn(Interruptible intr) { // pacote-privado
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Copie o código do código da seguinte forma:
interface InterruptAble { // Define uma interface interrompível
public void interrupção() lança InterruptedException;
}
classe abstrata InterruptSupport implementa InterruptAble {
privado volátil booleano interrompido = falso;
interruptor interrompível privado = new Interruptível() {
interrupção nula pública() {
interrompido = verdadeiro;
InterruptSupport.this.interrupt(); // Posição 3
}
};
public final boolean execute() lança InterruptedException {
tentar {
bloqueadoOn(interruptor); // Posição 1
if (Thread.currentThread().isInterrupted()) { // Interrompido imediatamente
interruptor.interrupt();
}
//Executa o código comercial
negócio();
} finalmente {
bloqueadoOn(null); // Posição 2
}
retorno interrompido;
}
público abstrato void bussiness() ;
público abstrato void interrupção();
// -- sun.misc.SharedSecrets --
static void bloqueadoOn(Interruptible intr) { // pacote-privado
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Descrição do código, alguns truques:
Posição 1: Use o métodoblockOn fornecido pela sun para vincular o gancho de processamento de evento Interruptível correspondente ao Thread especificado.
Posição 2: Após executar o código, limpe o gancho. Evite o impacto no próximo evento de processamento de thread ao usar o pool de conexões.
Posição 3: Define o método de processamento do gancho de evento Interruptível e chama de volta o método InterruptSupport.this.interrupt() As subclasses podem integrar e implementar sua própria lógica de negócios, como fechamento de fluxo de meia, etc.
usar:
Copie o código do código da seguinte forma:
classe InterruptRead estende InterruptSupport {
privado FileInputStream em;
@Substituir
negócio vazio público() {
File file = new File("/dev/urandom"); // Leia o buraco negro do Linux, nunca termine de ler
tentar {
in = novo FileInputStream(arquivo);
byte[] bytes = novo byte[1024];
enquanto (in.read(bytes, 0, 1024) > 0) {
//Thread.sleep(100);
// if (Thread.interrupted()) {// Método de verificação de interrupção anterior
//lança new InterruptedException("");
// }
}
} catch (Exceção e) {
lançar nova RuntimeException(e);
}
}
public FileInputStream getIn() {
retornar;
}
@Substituir
interrupção nula pública() {
tentar {
in.getChannel().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) lança exceção {
teste InterruptRead final = new InterruptRead();
Tópico t = novo Tópico() {
@Substituir
execução nula pública() {
início longo = System.currentTimeMillis();
tentar {
System.out.println("InterruptRead iniciar!");
teste.execute();
} catch (InterruptedException e) {
System.out.println("InterruptRead end! custo tempo: " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
};
t.start();
//Deixa o Read executar por 3 segundos primeiro
Thread.sleep(3000);
//Emite uma interrupção
t.interrupção();
}
Copie o código do código da seguinte forma:
classe InterruptRead estende InterruptSupport {
privado FileInputStream em;
@Substituir
negócio vazio público() {
File file = new File("/dev/urandom"); // Leia o buraco negro do Linux, nunca termine de ler
tentar {
in = novo FileInputStream(arquivo);
byte[] bytes = novo byte[1024];
enquanto (in.read(bytes, 0, 1024) > 0) {
//Thread.sleep(100);
// if (Thread.interrupted()) {// Método de verificação de interrupção anterior
//lança new InterruptedException("");
// }
}
} catch (Exceção e) {
lançar nova RuntimeException(e);
}
}
public FileInputStream getIn() {
retornar;
}
@Substituir
interrupção nula pública() {
tentar {
in.getChannel().close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) lança exceção {
teste InterruptRead final = new InterruptRead();
Tópico t = novo Tópico() {
@Substituir
execução nula pública() {
início longo = System.currentTimeMillis();
tentar {
System.out.println("InterruptRead iniciar!");
teste.execute();
} catch (InterruptedException e) {
System.out.println("InterruptRead end! custo tempo: " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
};
t.start();
//Deixa o Read executar por 3 segundos primeiro
Thread.sleep(3000);
//Emite uma interrupção
t.interrupção();
}
Introdução ao código-fonte jdk:
1. O gancho fornecido pela sun pode visualizar o código relevante do Sistema, linha: 1125
Copie o código do código da seguinte forma:
sun.misc.SharedSecrets.setJavaLangAccess(novo sun.misc.JavaLangAccess(){
public sun.reflect.ConstantPool getConstantPool(Classe classe) {
return klass.getConstantPool();
}
public void setAnnotationType(classe classe, tipo AnnotationType) {
classe.setAnnotationType(tipo);
}
public AnnotationType getAnnotationType(Classe classe) {
retornar klass.getAnnotationType();
}
público <E estende Enum<E>>
E[] getEnumConstantsShared(Class<E> classe) {
return klass.getEnumConstantsShared();
}
public void bloqueadoOn(Thread t, Interruptível b) {
t.blockedOn(b);
}
});
Copie o código do código da seguinte forma:
sun.misc.SharedSecrets.setJavaLangAccess(novo sun.misc.JavaLangAccess(){
public sun.reflect.ConstantPool getConstantPool(Classe classe) {
return klass.getConstantPool();
}
public void setAnnotationType(classe classe, tipo AnnotationType) {
classe.setAnnotationType(tipo);
}
public AnnotationType getAnnotationType(Classe classe) {
retornar klass.getAnnotationType();
}
público <E estende Enum<E>>
E[] getEnumConstantsShared(Class<E> classe) {
return klass.getEnumConstantsShared();
}
public void bloqueadoOn(Thread t, Interruptível b) {
t.blockedOn(b);
}
});
2.Thread.interrupt()
Copie o código do código da seguinte forma:
interrupção nula pública() {
if (isso! = Thread.currentThread())
verificarAcesso();
sincronizado (blockerLock) {
Interruptível b = bloqueador;
if (b! = nulo) {
interrupção0(); // Apenas para definir o sinalizador de interrupção
b.interrupt(); //Gancho de retorno de chamada
retornar;
}
}
interromper0();
}
Copie o código do código da seguinte forma:
interrupção nula pública() {
if (isso! = Thread.currentThread())
verificarAcesso();
sincronizado (blockerLock) {
Interruptível b = bloqueador;
if (b! = nulo) {
interrupção0(); // Apenas para definir o sinalizador de interrupção
b.interrupt(); //Gancho de retorno de chamada
retornar;
}
}
interromper0();
}
Para obter mais informações sobre o uso de Thread.stop, suspender, retomar e interromper, você pode dar uma olhada na documentação da Sun, como http://download.oracle.com/javase/6/docs/technotes/guides/concurrency /threadPrimitiveDeprecation.html
Por fim, vamos responder algumas das perguntas anteriores:
Pergunta 1: Qual é a relação entre o método Thread.interrupt() e InterruptedException? A exceção InterruptedException é acionada por interrupção?
Resposta: Thread.interrupt() lançará InterruptedException ativamente apenas em Object.wait(), .Object.join() e Object.sleep(). É comum em outros blocos, basta definir uma informação de flag de Thread, e o programa precisa processá-lo sozinho.
Copie o código do código da seguinte forma:
if (Thread.interrupted()) // Limpa o status interrompido!
lançar new InterruptedException();
Copie o código do código da seguinte forma:
if (Thread.interrupted()) // Limpa o status interrompido!
lançar new InterruptedException();
Pergunta 2: Em que estado Thread.interrupt() interromperá o trabalho do thread? EXECUTANDO ou BLOQUEANDO?
Resposta: O objetivo do design Thread.interrupt é principalmente lidar com threads em estado de bloco, como estados wait() e sleep(). No entanto, o cancelamento da tarefa pode ser suportado durante o design do programa, e o estado RUNNING também pode ser suportado. Por exemplo, Object.join() e alguns designs de canal nio que suportam interrupção.
Pergunta 3: A programação geral do Thread precisa prestar atenção às interrupções? Como lidar com isso em geral? Para que pode ser usado?
Resposta: Interromper o uso: operação de desbloqueio, suporte para cancelamento de tarefas, limpeza de dados, etc.
Pergunta 4: Qual é a diferença entre LockSupport.park() e unpark() e object.wait() e notify()?
responder:
1. Os assuntos são diferentes. LockSuport executa principalmente o processamento de bloqueio para Thread. Ele pode especificar o objeto de destino da fila de bloqueio e especificar um thread específico para ativar cada vez. Object.wait() toma o objeto como dimensão, bloqueia o thread atual e ativa um único (aleatório) ou todos os threads.
2. Os mecanismos de implementação são diferentes. Embora LockSuport possa especificar o objeto objeto do monitor, as filas de bloqueio de LockSuport e object.wait() não se cruzam. Você pode dar uma olhada no exemplo de teste. object.notifyAll() não pode ativar o Thread de bloqueio do LockSupport.
Pergunta 5: Qual é a utilidade do objeto bloqueador passado por LockSupport.park (objeto bloqueador)?
Resposta: O blcoker correspondente será registrado em um atributo parkBlocker do Thread. É muito conveniente monitorar objetos de bloqueio específicos através do comando jstack.
Copie o código do código da seguinte forma:
public static void park(bloqueador de objetos) {
Tópico t = Thread.currentThread();
setBlocker(t, blocker); //Definir o valor da propriedade Thread.parkBlocker
inseguro.park(falso, 0L);
setBlocker(t, null); // Limpa o valor da propriedade Thread.parkBlocker
}
Copie o código do código da seguinte forma:
public static void park(bloqueador de objetos) {
Tópico t = Thread.currentThread();
setBlocker(t, blocker); //Definir o valor da propriedade Thread.parkBlocker
inseguro.park(falso, 0L);
setBlocker(t, null); // Limpa o valor da propriedade Thread.parkBlocker
}
A descrição específica do javadoc do LockSupport também é relativamente clara. Você pode lê-la abaixo:
Pergunta 6: O LockSupport pode responder a eventos Thread.interrupt()? Será InterruptedException lançada?
Resposta: Ele pode responder a eventos de interrupção, mas não lançará InterruptedException. Em relação ao suporte do LockSupport para Thread.interrupte, dê uma olhada também na descrição no javadoc:
Código de teste relacionado
Copie o código do código da seguinte forma:
pacote 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;
classe pública LockSupportTest {
bloqueador estático privado de LockSupportTest = new LockSupportTest();
public static void main(String args[]) lança exceção {
lockSupportTest();
parkTest();
interromperParkTest();
interromperSleepTest();
interromperWaitTest();
}
/**
* Após o objeto LockSupport.park, tente obter o objeto Thread.blocker e chame seu único wakeup
*
* @throwsException
*/
private static void lockSupportTest() lança exceção {
Tópico t = doTest(new TestCallBack() {
@Substituir
public void callback() lança exceção {
//tente dormir 5s
System.out.println("bloqueador");
LockSupport.park(bloqueador);
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "lockSupportTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(150);
sincronizado (bloqueador) {
Campo campo = Thread.class.getDeclaredField("parkBlocker");
field.setAccessible (verdadeiro);
Objeto fBlocker = field.get(t);
System.out.println(bloqueador == fBlocker);
Thread.sleep(100);
System.out.println("notificarTudo");
bloqueador.notifyAll();
}
}
/**
* Se você tentar interromper um object.wait(), a InterruptedException correspondente será lançada.
*
* @throws InterruptedException
*/
private static void interrupçãoWaitTest() lança InterruptedException {
objeto final obj = new Objeto();
Tópico t = doTest(new TestCallBack() {
@Substituir
public void callback() lança exceção {
//tente dormir 5s
obj.wait();
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "interruptWaitTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
t.interrupt(); // Verifica se a interrupção é respondida durante o estacionamento
}
/**
* Se você tentar interromper Thread.sleep(), a InterruptedException correspondente será lançada.
*
* @throws InterruptedException
*/
private static void interrupçãoSleepTest() lança InterruptedException {
Tópico t = doTest(new TestCallBack() {
@Substituir
public void callback() lança exceção {
//tente dormir 5s
Thread.sleep(5000);
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "interruptSleepTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
t.interrupt(); // Verifica se a interrupção é respondida durante o estacionamento
}
/**
* Tente interromper um LockSupport.park(), haverá uma resposta, mas nenhuma exceção InterruptedException será lançada
*
* @throws InterruptedException
*/
private static void interrupçãoParkTest() lança InterruptedException {
Tópico t = doTest(new TestCallBack() {
@Substituir
retorno de chamada público void() {
//Tente estacionar seu próprio tópico
LockSupport.parkNanos(bloqueador, TimeUnit.SECONDS.toNanos(5));
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "interruptParkTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
t.interrupt(); // Verifica se a interrupção é respondida durante o estacionamento
}
/**
* Tente interromper um LockSupport.unPark(), haverá uma resposta
*
* @throws InterruptedException
*/
private static void parkTest() lança InterruptedException {
Tópico t = doTest(new TestCallBack() {
@Substituir
retorno de chamada público void() {
//Tente estacionar seu próprio tópico
LockSupport.park(bloqueador);
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "parkTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
LockSupport.unpark(t);
t.interrupção();
}
public static Thread doTest(chamada final TestCallBack) {
retornar novo Thread() {
@Substituir
execução nula pública() {
Arquivo arquivo = new File("/dev/urandom"); // Ler o buraco negro do Linux
tentar {
FileInputStream in = new FileInputStream(arquivo);
byte[] bytes = novo byte[1024];
enquanto (in.read(bytes, 0, 1024) > 0) {
if (Thread.interrupted()) {
lançar new InterruptedException("");
}
System.out.println(bytes[0]);
Thread.sleep(100);
início longo = System.currentTimeMillis();
chamada.callback();
System.out.println(call.getName() + "custo de finalização do retorno de chamada:"
+ (System.currentTimeMillis() - início));
}
} catch (Exceção e) {
e.printStackTrace();
}
}
};
}
}
interfaceTestCallBack {
public void callback() lança exceção;
public String getNome();
}
Copie o código do código da seguinte forma:
pacote 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;
classe pública LockSupportTest {
bloqueador estático privado de LockSupportTest = new LockSupportTest();
public static void main(String args[]) lança exceção {
lockSupportTest();
parkTest();
interromperParkTest();
interromperSleepTest();
interromperWaitTest();
}
/**
* Após o objeto LockSupport.park, tente obter o objeto Thread.blocker e chame seu único wakeup
*
* @throwsException
*/
private static void lockSupportTest() lança exceção {
Tópico t = doTest(new TestCallBack() {
@Substituir
public void callback() lança exceção {
//tente dormir 5s
System.out.println("bloqueador");
LockSupport.park(bloqueador);
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "lockSupportTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(150);
sincronizado (bloqueador) {
Campo campo = Thread.class.getDeclaredField("parkBlocker");
field.setAccessible (verdadeiro);
Objeto fBlocker = field.get(t);
System.out.println(bloqueador == fBlocker);
Thread.sleep(100);
System.out.println("notificarTudo");
bloqueador.notifyAll();
}
}
/**
* Se você tentar interromper um object.wait(), a InterruptedException correspondente será lançada.
*
* @throws InterruptedException
*/
private static void interrupçãoWaitTest() lança InterruptedException {
objeto final obj = new Objeto();
Tópico t = doTest(new TestCallBack() {
@Substituir
public void callback() lança exceção {
//tente dormir 5s
obj.wait();
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "interruptWaitTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
t.interrupt(); // Verifica se a interrupção é respondida durante o estacionamento
}
/**
* Se você tentar interromper Thread.sleep(), a InterruptedException correspondente será lançada.
*
* @throws InterruptedException
*/
private static void interrupçãoSleepTest() lança InterruptedException {
Tópico t = doTest(new TestCallBack() {
@Substituir
public void callback() lança exceção {
//tente dormir 5s
Thread.sleep(5000);
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "interruptSleepTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
t.interrupt(); // Verifica se a interrupção é respondida durante o estacionamento
}
/**
* Tente interromper um LockSupport.park(), haverá uma resposta, mas nenhuma exceção InterruptedException será lançada
*
* @throws InterruptedException
*/
private static void interrupçãoParkTest() lança InterruptedException {
Tópico t = doTest(new TestCallBack() {
@Substituir
retorno de chamada público void() {
//Tente estacionar seu próprio tópico
LockSupport.parkNanos(bloqueador, TimeUnit.SECONDS.toNanos(5));
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "interruptParkTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
t.interrupt(); // Verifica se a interrupção é respondida durante o estacionamento
}
/**
* Tente interromper um LockSupport.unPark(), haverá uma resposta
*
* @throws InterruptedException
*/
private static void parkTest() lança InterruptedException {
Tópico t = doTest(new TestCallBack() {
@Substituir
retorno de chamada público void() {
//Tente estacionar seu próprio tópico
LockSupport.park(bloqueador);
System.out.println("acorde agora!");
}
@Substituir
public String getNome() {
retornar "parkTest";
}
});
t.start(); // Inicia o thread de leitura
Thread.sleep(2000);
LockSupport.unpark(t);
t.interrupção();
}
public static Thread doTest(chamada final TestCallBack) {
retornar novo Thread() {
@Substituir
execução nula pública() {
Arquivo arquivo = new File("/dev/urandom"); // Ler o buraco negro do Linux
tentar {
FileInputStream in = new FileInputStream(arquivo);
byte[] bytes = novo byte[1024];
enquanto (in.read(bytes, 0, 1024) > 0) {
if (Thread.interrupted()) {
lançar new InterruptedException("");
}
System.out.println(bytes[0]);
Thread.sleep(100);
início longo = System.currentTimeMillis();
chamada.callback();
System.out.println(call.getName() + "custo de finalização do retorno de chamada:"
+ (System.currentTimeMillis() - início));
}
} catch (Exceção e) {
e.printStackTrace();
}
}
};
}
}
interfaceTestCallBack {
public void callback() lança exceção;
public String getNome();
}
Finalmente <BR>descobri que o artigo estava ficando cada vez mais longo, então simplesmente postei-o no fórum para todos discutirem juntos. Afinal, o artigo descreveu apenas algumas coisas de nível de uso e não introduziu o Thread da operação. sistema ou implementação nativa do sol Para alguns mecanismos, Daniumen que estão familiarizados com esta área também podem expressar suas opiniões.