A análise mais abrangente do uso de multithreading Java. Se você não realizou pesquisas aprofundadas sobre o mecanismo de multithreading da Java, este artigo pode ajudá-lo a entender mais os princípios e métodos de uso da Java Multithreading.
1. Crie um tópico
Existem duas maneiras de criar threads em Java: usando a classe Thread e usando a interface executável. Ao usar a interface executável, você precisa criar uma instância do thread. Portanto, se você está estabelecendo um fio através da classe Thread ou da interface executável, deve estabelecer uma instância da classe Thread ou de sua subclasse. Construtor de threads:
Método 1: herdar a classe de threads e substituir o método de execução
public class ThreadDemo1 {public static void main (string [] args) {Demo d = new Demo (); d.start (); for (int i = 0; i <60; i ++) {System.out.println (thread.currentThread (). getName ()+i); }}} classe Demo estende thread {public void run () {for (int i = 0; i <60; i ++) {System.out.println (thread.currentThread (). getName ()+i); }}}Método 2:
public class ThreadDemo2 {public static void main (string [] args) {Demo2 d = new Demo2 (); Thread t = novo thread (d); t.start (); for (int x = 0; x <60; x ++) {System.out.println (thread.currentThread (). getName ()+x); }}} classe Demo2 implementa runnable {public void run () {for (int x = 0; x <60; x ++) {System.out.println (thread.currentThread (). getName ()+x); }}}2. O ciclo de vida dos threads
Assim como as pessoas têm nascimento, velhice, doença e morte, os fios também precisam passar por quatro estados diferentes: Iniciar (esperar), correr, suspender e parar. Todos os quatro estados podem ser controlados por métodos na classe Thread. A seguir, é apresentado um método relacionado a esses quatro estados na classe de threads.
// Start Thread
publicVoid Start ();
publicVoid run ();
// suspender e acordar tópicos
publicVoid currume (); // não recomendado para usar
PublicVoid suspender (); // não recomendado para usar
PublicstaticVoid Sleep (Long Millis);
PublicstaticVoid Sleep (Long Millis, Int Nanos);
// encerrar o tópico
PublicVoid Stop (); // não recomendado para usar
PublicVoid Interrupt ();
// Obtenha o estado do tópico
PublicBoolean Isalive ();
PublicBoolean IsInterrupted ();
publicstaticBoolean Interromped ();
// Método de junção
PublicVoid junção () lança interruptedException;
Depois que o thread for estabelecido, ele não executa o código no método de execução imediatamente, mas está em um estado de espera. Quando o thread está em um estado de espera, você pode usar o método da classe Thread para definir várias propriedades do thread, como a prioridade do Thread (SetPriority), o nome do thread (SetName) e o Type Thread (SetDaemon), etc.
Depois de chamar o método de início, o thread começa a executar o código no método de execução. O tópico entra no estado em execução. Você pode usar o método isalivo da classe Thread para determinar se o encadeamento está em estado de execução. Quando o tópico está no estado em execução, o retorno isalivo é verdadeiro. Quando os retornos isalivos falsos, o tópico pode estar no estado de espera ou no estado de parada. O código a seguir demonstra a comutação entre os três estados de criação, execução e parada de threads e produz o valor de retorno isalivo correspondente.
Depois que o thread começar a executar o método de execução, o thread não sairá até que o método de execução seja executado. No entanto, durante a execução de um encadeamento, o encadeamento pode ser interrompido temporariamente por dois métodos. Esses dois métodos são suspensos e dormem. Depois de suspender o thread com suspensão, o thread pode ser despertado através do método de currículo. Depois de usar o sono para dormir, o thread só pode ser colocado no estado pronto após o tempo definido (depois que o thread dorme, o thread não pode executar imediatamente, mas apenas entra no estado pronto e aguarda o cronograma do sistema).
Há duas coisas a serem observadas ao usar o método do sono:
1. O método do sono possui dois formulários de sobrecarga. Um dos formulários de sobrecarga pode não apenas ser definido como milissegundos, mas também nanossegundos (1.000.000 de nanossegundos equivale a 1 milissegundo). No entanto, as máquinas virtuais Java na maioria das plataformas de sistema operacional não podem ser precisas para os nanossegundos; portanto, se os nanossegundos estiverem definidos para dormir, a máquina virtual Java levará os milissegundos mais próximos desse valor.
2. Ao usar o método do sono, você deve usar lances ou experimentar {…} Catch {…}. Como o método de execução não pode usar os arremessos, você só pode usar tente {…} catch {…}. Quando o thread estiver dormindo, o sono lançará uma exceção interrupta ao interromper o encadeamento usando o método de interrupção. O método do sono é definido da seguinte maneira:
PublicstaticVoid Sleep (Long Millis) lança interruptedException
PublicstaticVoid Sleep (Long Millis, Int Nanos) lança interruptedException
Existem três maneiras de encerrar o thread.
1. Use o sinalizador de saída para fazer a saída do encadeamento normalmente, ou seja, o thread termina quando o método de execução é concluído.
2. Use o método de parada para encerrar com força o encadeamento (esse método não é recomendado porque a parada é a mesma que suspensa e retomar e também pode ter resultados imprevisíveis).
3. Use o método de interrupção para interromper o thread.
1. Use a bandeira de saída para encerrar o tópico
Quando o método de execução é executado, o thread sairá. Mas às vezes o método de corrida nunca termina. Por exemplo, o uso de threads para ouvir solicitações de clientes em programas de servidor ou outras tarefas que exigem processamento de loop. Nesse caso, essas tarefas geralmente são colocadas em um loop, como o loop enquanto o loop. Se você deseja que o loop seja executado para sempre, pode usar enquanto (true) {…} para lidar com isso. No entanto, se você deseja fazer a saída do loop no tempo em uma certa condição, a maneira mais direta é definir um sinalizador do tipo booleano e controlar se o loop de tempo sai definindo esse sinalizador como true ou falso. Aqui está um exemplo de encerrar um encadeamento usando o sinalizador de saída.
A função do método de junção é transformar o encadeamento de execução assíncrono em execução síncrona. Ou seja, quando o método de início da instância do thread for chamado, o método retornará imediatamente. Se um valor calculado por este thread precisar ser usado após a chamada do método de início, o método de junção deverá ser usado. Se você não usar o método de junção, não se pode garantir que, quando uma instrução por trás do método de início for executada, o thread será executado. Depois de usar o método de junção, o programa não será executado até que o thread sai. O código a seguir demonstra o uso de junção.
3. Questões de segurança multithread
Causa do problema: quando várias instruções estão operando no mesmo thread para compartilhar dados, um thread executa apenas parte de várias instruções, mas ainda não terminou de executá -lo e outro thread participa da execução, resultando em um erro no compartilhamento de dados.
Solução: Para várias instruções que compartilham dados com várias operações, apenas um thread pode ser executado. Durante o processo de execução, outros threads não são executados.
Sincronize blocos de código:
classe pública threadDemo3 {public static void main (string [] args) {ticket t = new Ticket (); Thread t1 = novo thread (t, "janela um"); Tópico T2 = novo thread (t, "Janela dois"); Thread t3 = novo thread (t, "janela três"); Thread t4 = novo thread (t, "janela quatro"); t1.start (); t2.start (); t3.start (); t4.start (); }} classe de classe implementa o runnable {private int ticket = 400; public void run () {while (true) {sincronizado (new object ()) {try {thread.sleep (1); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } if (ticket <= 0) quebra; System.out.println (thread.currentThread (). GetName ()+"--- vender"+ticket--); }}}}Funções síncronas
classe pública threadDemo3 {public static void main (string [] args) {ticket t = new Ticket (); Thread t1 = novo thread (t, "janela um"); Tópico T2 = novo thread (t, "Janela dois"); Thread t3 = novo thread (t, "janela três"); Thread t4 = novo thread (t, "janela quatro"); t1.start (); t2.start (); t3.start (); t4.start (); }} classe de classe implementa o runnable {private int ticket = 4000; public sincronizado void Saleticket () {if (ticket> 0) System.out.println (thread.currentThread (). getName ()+"Selled"+Ticket--); } public void run () {while (true) {Saleticket (); }}}Bloqueio de função síncrona é esta função de sincronização estática Lock é classe
Comunicação entre threads
public class ThreadDemo3 {public static void main (string [] args) {classe PERSON {public String Name; gênero de cordas privadas; public void Set (Nome da String, String Gênero) {this.name = name; this.gnder = gênero; } public void get () {System.out.println (this.name+"...."+this.gender); }} Pessoa final p = new Person (); novo thread (new runnable () {public void run () {int x = 0; while (true) {if (x == 0) {p.set ("zhang san", "masculino");} else {p.set ("lili", "nv");} x = (x+1)%2;}}}). novo thread (novo runnable () {public void run () {while (true) {p.get ();}}}). start (); }}/ *Zhang san .... masculino zhang san .... lili masculino .... nvlili .... masculino zhang san .... nvlili .... masculino */Modifique o código acima
public class ThreadDemo3 {public static void main (string [] args) {classe PERSON {public String Name; gênero de cordas privadas; public void Set (Nome da String, String Gênero) {this.name = name; this.gnder = gênero; } public void get () {System.out.println (this.name+"...."+this.gender); }} Pessoa final p = new Person (); novo thread (new runnable () {public void run () {int x = 0; while (true) {sincronizado (p) {if (x == 0) {p.set ("zhang san", "masculino");} else {p.set ("lili", "nv");}} (x+1) 2; novo thread (novo runnable () {public void run () {while (true) {synchronized (p) {p.get ();}}}}}). start (); } } /* lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv lili....nv Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San....male Zhang San .... Zhang masculino San .... masculino */Esperando pelo mecanismo de despertar
/**Thread Waiting Wake-up Mecanism*Aguarde e o despertar deve ser o mesmo bloqueio*/classe pública ThreadDemo3 {private estático sinalizadores booleanos = false; public static void main (string [] args) {classe PERSON {public String Name; gênero de cordas privadas; public void Set (Nome da String, String Gênero) {this.name = name; this.gnder = gênero; } public void get () {System.out.println (this.name+"...."+this.gender); }} Pessoa final p = new Person (); novo thread (new runnable () {public void run () {int x = 0; while (true) {synchronized (p) {if (sinalizadores) tente {p.wait ();} catch (interruptException e) {// tdo auto-generado bloco de captura ePrintStack (); } else {p.set ("lili", "nv"); novo thread (novo runnable () {public void run () {while (true) {synchronized (p) {if (! sinalizadores) tente {p.wait ();} catch (interruptedException e) {// topo-generado bloco de captura ePrintStack ();}; p.get (); flags = flagin; }).começar(); }}Mecanismo de produção e consumo um
classe pública threadDemo4 {private estático sinalizadores booleanos = false; public static void main (string [] args) {classe bens {private string name; privado int num; public sincronizado void Produce (nome da string) {if (sinalizadores) tente {wait (); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } this.name = nome+"número:"+num ++; System.out.println ("Produzido ......"+this.name); sinalizadores = true; notifyAll (); } public sincronizado void consumo () {if (! sinalizadores) tente {wait (); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } System.out.println ("*******"+nome); sinalizadores = false; notifyAll (); }} bens finais g = new bens (); novo thread (novo runnable () {public void run () {while (true) {g.produce ("Product");}}}). start (); novo thread (novo runnable () {public void run () {while (true) {g.consume ();}}}). start (); }}Mecanismo de produção e consumo 2
classe pública threadDemo4 {private estático sinalizadores booleanos = false; public static void main (string [] args) {classe bens {private string name; privado int num; public sincronizado void Produce (nome da string) {while (sinalizadores) tente {wait (); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } this.name = nome+"número:"+num ++; System.out.println (thread.currentThread (). GetName ()+"produzido ..."+this.name); sinalizadores = true; notifyAll (); } public sincronizado void consume () {while (! sinalizadores) tente {wait (); } catch (interruptedException e) {// TODO BLOCO DE CATCH AUTOGERATIDO E.PRINTSTACKTRACE (); } System.out.println (thread.currentThread (). GetName ()+"consumido *********"+nome); sinalizadores = false; notifyAll (); }} bens finais g = new bens (); new Thread (new Runnable () {public void run () {while (true) {g.produce ("Product");}}}, "Produce (" Product ");}}}," Produce ("Product");}}}, "produzir (" Product ");}}}}}}}; }, "Consumidor nº 1"). Start (); Consumido ******* Número de commodities: 48050Produtor nº 1 Produzido ... Número de commodities: 48051Consumer No. 2 Consumido **** Número de commodities: 48051Producedor No. 2 Produzido ... Número de commodities: 4802: 48052Consumer 2. 48053Consumer No. 1 foi consumido ******* Número de commodities: 48053 PRODUCER No. 1 foi produzido ... Número de commodities: 48054Consumer No. 2 foi consumido ********* Número de commodities: 48054Producker No. 2 foi produzido ... número de comodidade: 480555Cons. 48055*/O exposto acima é a compilação de informações multi-threades Java. Continuaremos a adicionar conhecimento relevante no futuro. Obrigado pelo seu apoio a este site!