Start thread:
1. Descrição da diferença entre start () e run ()
START (): sua função é iniciar um novo thread e o novo thread executará o método Run () correspondente. Start () não pode ser chamado repetidamente.
RUN (): RUN () pode ser chamado repetidamente como métodos de membros comuns. Se você ligar para o RUN () separadamente, o RUN () será executado no thread atual e o novo thread não será iniciado!
A seguir, é apresentado um código a ser explicado.
classe mythread estende thread {public void run () {...}}; mythread mythread = new mythread (); mythread.start () inicia um novo thread e executa o método run () no novo thread.
Mythread.run () executará o método run () diretamente no thread atual e não iniciará um novo thread para executar run ().
2. Exemplo da diferença entre start () e run ()
Abaixo, demonstre a diferença entre eles com um exemplo simples. O código -fonte é o seguinte:
// Demo.java Código -fonte do Mythread estende thread {public mythread (nome da string) {super (nome); } public void run () {System.out.println (thread.currentThread (). getName ()+"está em execução"); }}; public class Demo {public static void main (string [] args) {thread mythread = new mythread ("mythread"); System.out.println (thread.currentThread (). GetName ()+"ligue para mythread.run ()"); mythread.run (); System.out.println (thread.currentThread (). GetName ()+"ligue para mythread.start ()"); mythread.start (); }} Resultados em execução:
principal chamado mythread.run () main é o runningmain chamado mythread.start () mythread está executando
Resultados Descrição:
(1) Thread.currentThread (). GetName () é usado para obter o nome de "Thread atual". O thread atual refere -se ao encadeamento que está programado para executar na CPU.
(2) Mythread.run () é chamado em "Main Thread Main", e o método run () é executado diretamente no "Principal Main Main".
(3) mythread.start () iniciará o "Thread Mythread". Depois que o "Thread Mythread" é iniciado, o método run () será chamado; Neste momento, o método run () é executado no "Thread Mythread".
Interrupções e terminações de threads
1. Interrupção do thread: interrupção ()
A função de interrupção () é interromper o thread.
Este tópico é autorizado a se interromper; Quando outros threads chamam o método interromp () deste thread, a permissão será verificada através do checkAccess (). Isso pode lançar uma exceção de segurança.
Se o tópico estiver em um estado de bloqueio: chamando espera (), espere (longo) ou espere (longo, int) do thread, a transformará em um estado de espera (bloqueando) ou chamando junção (), junte -se (longa), junte -se (longa, int), sono (longo), sono (longo, int) do fio, também a transformará em um estado bloqueador. Se o thread chamar seu método interromp () quando estiver bloqueando, seu "estado de interrupção" será limpo e uma interrupção será recebida. Por exemplo, um thread entra em um estado de bloqueio através da espera (), e o thread é interrompido por interrupt (); A chamada interrupção () definirá imediatamente o sinalizador de interrupção do encadeamento como "True", mas como o thread está em um estado de bloqueio, o "sinalizador de interrupção" será imediatamente liberado para "false" e uma interrupção será gerada.
Se o thread for bloqueado em um seletor seletor, então quando for interrompido pelo interrupto (); O sinalizador de interrupção do thread está definido como true e será retornado imediatamente da operação de seleção.
Se não pertencer à situação mencionada acima, quando o thread for interrompido através da interrupção (), seu sinalizador de interrupção será definido como "true".
Interromper um "encadeamento terminado" não causará nenhuma operação.
2. Terminação de rosca
Recomenda -se que os métodos Stop () e Suspender () em Thread não sejam usados devido à sua insegurança inerente!
Em seguida, discutirei primeiro o método de rescisão dos threads no "estado de bloqueio" e "estado em execução", respectivamente, e depois resumirá um método geral.
1. Encerrar o fio no "estado de bloqueio"
Geralmente, encerramos um fio em um "estado de bloqueio" ao "interromper".
Quando o thread entra em um estado de bloqueio devido a ser chamado de sono (), espera (), ingressar () e outros métodos; Se a interrupção () do thread for chamada neste momento, a marca de interrupção do thread será definida como true. Como está em um estado de bloqueio, o sinalizador de interrupção será limpo e uma exceção interrompedException será gerada. Colocar o interruptedException até que seja apropriado pode encerrar o segmento, no formulário da seguinte forma:
@OverridePublic void run () {try {while (true) {// Execute a tarefa ...}} Catch (interruptedException ie) {// Devido a uma exceção interrompida de exceção, saia do loop (true) e o thread termina! }} NOTA: Quando a tarefa é executada continuamente no while (true), quando o thread está em um estado de bloqueio, a chamada para interromper () do thread gera uma interrupção interrompedException. A captura interrompida está do lado de fora enquanto (verdadeira), saindo assim do laço (verdadeiro)!
NOTA: A captura de interrupções de exceção é geralmente colocada fora do corpo (verdadeiro) do corpo do loop, de modo que, no tempo (verdadeiro) o loop saia quando uma exceção é gerada. Caso contrário, se a interrupção interrompida estiver dentro do tempo (verdadeiro) do corpo do loop, é necessário adição adicional e processamento de saída. O formulário é o seguinte:
@OverridePublic void run () {while (true) {try {// Execute Task ...} Catch (interruptedException ie) {// interruptedException está no tempo (true) corpo de loop. // Quando o thread gera uma exceção interrompedException, enquanto (True) pode continuar a ser executado! Precisa sair manualmente quebra; }}} Nota: A exceção acima do interruptedException é capturada em Whle (true). Quando uma exceção interrompedException é gerada, ela não é tratada por captura e ainda está no tempo (verdadeiro) do corpo de loop; Para sair do corpo (verdadeiro) do corpo de loop, uma operação adicional de sair do tempo (verdadeira) precisa ser executada.
2.
Geralmente, encerramos um fio em um "estado de corrida" "marcando". Entre eles, inclui "sinalizador de interrupção" e "Adicionar sinalizador adicional".
(1) encerrar o encadeamento através de "sinalizador de interrupção".
O formulário é o seguinte:
@OverridePublic void run () {while (! IsInterrupted ()) {// Execute Task ...}} Descrição: isInterrupted () determina se o sinalizador de interrupção do thread é verdadeiro. Quando o tópico está em estado de corrida e precisamos encerrá -lo; O método interromp () do Thread () pode ser chamado, e o sinalizador de interrupção do encadeamento está marcado como verdadeiro, ou seja, o ISInterrupted () retornará true. Neste ponto, o loop while será expulso.
NOTA: interrupção () não encerra os threads em "estado de corrida"! Ele define o sinalizador de interrupção do thread como true.
(2) Passe "Adicione marcas adicionais".
O formulário é o seguinte:
sinalizador booleano volátil privado = true; protegido void stopTask () {flag = false;}@substituirpublic void run () {while (flag) {// executar tarefa ...}} Descrição: Existe uma tag de sinalizador no thread e seu valor padrão é verdadeiro; e fornecemos StopTask () para definir a tag de sinalizador. Quando precisamos encerrar o encadeamento, chamando o método stopTask () do thread pode fazer com que o encadeamento saia do loop while.
Nota: O sinalizador é definido como o tipo volátil para garantir a visibilidade do sinalizador. Ou seja, depois que outros threads modificam o sinalizador através do StopTask (), este thread pode ver o valor do sinalizador modificado.
Abrangente os métodos de rescisão dos threads em "estado de bloqueio" e "estado de corrida", os threads de rescisão mais comuns são os seguintes:
@OverridePublic void run () {try {// 1. IsInterrupted () garante que o thread será encerrado enquanto a interrupção estiver marcada. while (! isInterrupted ()) {// Execute Task ...}} Catch (interruptedException ie) {// 2. Exceção de interrupções de exceção garante que, quando ocorre uma exceção interrompida, o encadeamento é encerrado. }} 3. Exemplo de encadeamento de encerramento
interromp () é frequentemente usado para encerrar um encadeamento de "estado de bloqueio". Consulte o exemplo a seguir:
// Demo1.Java Código -fonte do Mythread estende thread {public mythread (nome da string) {super (nome); } @Override public void run () {try {int i = 0; while (! isInterrupted ()) {thread.sleep (100); // Dormir 100ms i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") loop"+i); }} catch (interruptEdException e) {System.out.println (thread.currentThread (). getName ()+"("+this.getState ()+") Catch interrompedException."); }}} classe pública Demo1 {public static void main (string [] args) {try {thread t1 = new mythread ("t1"); // Crie um novo "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") é novo."); t1.start (); // Iniciar "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") é iniciado."); // O fio principal dorme por 300ms e, em seguida, o encadeamento principal envia uma instrução de "interrompa" para T1. Thread.sleep (300); t1.Interrupt (); System.out.println (t1.getName ()+"("+t1.getState ()+") é interrompido."); // O encadeamento principal dorme por 300ms e verifica o status de T1. Thread.sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") é interrompido agora."); } catch (interruptedException e) {e.printStackTrace (); }}} Resultados em execução:
T1 (novo) é novo.t1 (runnable) é iniciado.t1 (runnable) loop 1t1 (runnable) loop 2t1 (timed_waiting) é interrompido.t1 (runnable) catch interruptedException.t1 (encerrado) está interrompido agora.
Resultados Descrição:
(1) O encadeamento principal principal cria thread t1 através do novo mythread ("T1") e, em seguida, inicia o encadeamento T1 a T1.start ().
(2) Após o início do T1, seu sinalizador de interrupção será verificado continuamente. Se a bandeira de interrupção for "falsa", ele dormirá por 100ms.
(3) Depois que o T1 dorme, ele mudará para a linha principal principal; Quando o thread principal é executado novamente, o T1.Interrup () será executado para interromper o thread T1. Depois que o T1 recebe a instrução de interrupção, o sinalizador de interrupção do T1 será definido como "FALSE" e uma interrupção será lançada. No método Run () de T1, é uma exceção capturada fora do corpo do loop; Portanto, o loop é encerrado.
Fizemos uma pequena modificação para o resultado acima e movimentamos o bloco de código que capturou a exceção interrompedException no método run () para o corpo do loop while.
// Demo2.Java Código -fonte do Mythread estende thread {public mythread (nome da string) {super (nome); } @Override public void run () {int i = 0; while (! isInterrupted ()) {tente {thread.sleep (100); // durma para 100ms} catch (interruptEdException ie) {System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") Catch interruptEdException."); } i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") loop"+i); }}} classe pública Demo2 {public static void main (string [] args) {try {thread t1 = new mythread ("t1"); // Crie um novo "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") é novo."); t1.start (); // Iniciar "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") é iniciado."); // O fio principal dorme por 300ms e, em seguida, o encadeamento principal envia uma instrução de "interrompa" para T1. Thread.sleep (300); t1.Interrupt (); System.out.println (t1.getName ()+"("+t1.getState ()+") é interrompido."); // O encadeamento principal dorme por 300ms e verifica o status de T1. Thread.sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") é interrompido agora."); } catch (interruptedException e) {e.printStackTrace (); }}} Resultados em execução:
T1 (novo) é novo.t1 (runnable) é iniciado.t1 (runnable) loop 1t1 (runnable) loop 2t1 (timed_waiting) é interrompido.t1 (runnable) catch interruptException.t1 (runnable) loop 3t1 (runnable) loop 4t1 (runnable) (runnable) loop 3t1 (runnable) lOOP 4T1 (runnable) (runnable) lOop 3T1 (runnable) 4t1 (runnable) (runnable) lOop 3T1 (runnable) 4t1 (runnable) (runnable) lOop 3T1 (runnable) 4t1 (runnable). (Runnable) Loop 6T1 (Runnable) Loop 7T1 (Runnable) Loop 8T1 (Runnable) Loop 9 ...
Resultados Descrição:
O programa entrou em um loop morto!
Por que isso está acontecendo? Isso ocorre porque o T1 é interrompido pelo interrupto () quando está "esperando (bloqueando) o estado". No momento, a bandeira de interrupção é limpa [que é interrompida () retornará falsa], e uma exceção interrompida é lançada [essa exceção é capturada no corpo do lago]. Portanto, o T1 entrará naturalmente um ciclo vicioso.
Para resolver esse problema, precisamos processamento extra para sair do loop no tempo ao capturar a exceção. Por exemplo, adicionar interrupção ou retorno ao Mythread Catch (InterruptEdException) pode resolver o problema.
Aqui está um exemplo de um tópico que encerra um "estado de status" "Adicionando tags adicionais":
// Demo3.Java Código -fonte do Mythread estende thread {sinalizador booleano volátil privado = true; public void stopTask () {flag = false; } public mythread (nome da string) {super (nome); } @Override public void run () {synchronized (this) {try {int i = 0; while (flag) {thread.sleep (100); // Dormir 100ms i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") loop"+i); }} catch (interruptEdException ie) {System.out.println (thread.currentThread (). getName ()+"("+this.getState ()+") Catch interrompedException."); }}}} public class Demo3 {public static void main (string [] args) {try {mythread t1 = new mythread ("t1"); // Crie um novo "Thread T1" System.out.println (t1.getName ())+"("+t1.getState ()+") é novo."); t1.start (); // Iniciar "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") é iniciado."); // O fio principal dorme por 300ms e, em seguida, o encadeamento principal envia uma instrução de "interrompa" para T1. Thread.sleep (300); t1.stopTask (); System.out.println (t1.getName ()+"("+t1.getState ()+") é interrompido."); // O encadeamento principal dorme por 300ms e verifica o status de T1. Thread.sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") é interrompido agora."); } catch (interruptedException e) {e.printStackTrace (); }}} Resultados em execução:
T1 (novo) é novo.t1 (runnable) é iniciado.t1 (runnable) loop 1t1 (runnable) loop 2t1 (timed_waiting) é interrompido.t1 (runnable) loop 3t1 (encerrado) é interrompido agora.