1. Crie um tópico
Existem duas maneiras de criar threads em Java: usando a classe Thread e usando a interface Runnable. Ao usar a interface Runnable, você precisa criar uma instância Thread. Portanto, quer você crie um thread por meio da classe Thread ou da interface Runnable, você deve criar uma instância da classe Thread ou de sua subclasse. Construtor de thread:
Método 1: herdar a classe Thread e substituir o método run
}
}
classe Demo estende Thread{
execução nula pública(){
for(int i=0;i<60;i++){
System.out.println(Thread.currentThread().getName()+i);
}
}
}
Assim como as pessoas nascem, envelhecem, adoecem e morrem, os fios também passam por quatro estados diferentes: iniciar (esperar), correr, pendurar e parar. Esses quatro estados podem ser controlados por meio de métodos da classe Thread. Os métodos relacionados a esses quatro estados na classe Thread são fornecidos abaixo.
O thread não executa o código no método run imediatamente após ser estabelecido, mas está em estado de espera. Quando o thread está no estado de espera, você pode definir vários atributos do thread por meio dos métodos da classe Thread, como a prioridade do thread (setPriority), o nome do thread (setName) e o tipo de thread (setDaemon).
Quando o método start é chamado, o thread começa a executar o código no método run. O thread entra no estado de execução. Você pode usar o método isAlive da classe Thread para determinar se o thread está em execução. Quando o thread está no estado de execução, isAlive retorna verdadeiro. Quando isAlive retorna falso, o thread pode estar no estado de espera ou no estado parado. O código a seguir demonstra a alternância entre os três estados de criação, execução e parada do thread e gera o valor de retorno isAlive correspondente.
Depois que o thread começar a executar o método run, ele não será encerrado até que o método run seja concluído. No entanto, durante a execução do thread, existem dois métodos que podem ser usados para interromper temporariamente a execução do thread. Esses dois métodos são suspender e dormir. Depois de usar suspend para suspender um thread, você pode ativá-lo por meio do método resume. Depois de usar sleep para fazer o thread dormir, o thread só pode estar no estado pronto após o tempo definido (após o término do sono do thread, o thread pode não ser executado imediatamente, mas apenas entra no estado pronto, aguardando o agendamento do sistema) .
Há dois pontos a serem observados ao usar o método sleep:
1. O método sleep tem duas formas sobrecarregadas. Uma das formas sobrecarregadas pode definir não apenas milissegundos, mas também nanossegundos (1.000.000 nanossegundos é igual a 1 milissegundo). No entanto, a máquina virtual Java na maioria das plataformas de sistema operacional não tem precisão de nanossegundos. Portanto, se os nanossegundos forem configurados para suspensão, a máquina virtual Java usará o milissegundo mais próximo desse valor.
2. Throws ou try{...}catch{...} devem ser usados ao usar o método sleep. Como o método run não pode usar throws, você só pode usar try{...}catch{...}. Quando o thread está em suspensão e o método de interrupção é usado para interrompê-lo, sleep lançará uma InterruptedException. O método sleep é definido da seguinte forma:
Existem três maneiras de encerrar um thread.
1. Use o sinalizador de saída para fazer o thread sair normalmente, ou seja, o thread termina quando o método de execução é concluído.
2. Use o método stop para encerrar o thread à força (esse método não é recomendado porque parar, assim como suspender e retomar, também pode produzir resultados imprevisíveis).
3. Use o método de interrupção para interromper o thread.
1. Encerre o thread usando o sinalizador de saída
Quando o método run for executado, o thread será encerrado. Mas às vezes o método run nunca termina. Por exemplo, threads são usados em programas de servidor para monitorar solicitações de clientes ou outras tarefas que requerem processamento cíclico. Nesse caso, essas tarefas geralmente são colocadas em um loop, como um loop while. Se você quiser que o loop seja executado para sempre, você pode usar while(true){...} para lidar com isso. Mas se você quiser fazer o loop while sair sob uma determinada condição, a maneira mais direta é definir um sinalizador do tipo booleano e definir esse sinalizador como verdadeiro ou falso para controlar se o loop while será encerrado. Um exemplo de encerramento de um thread usando o sinalizador de saída é fornecido abaixo.
A função do método join é fazer com que threads de execução assíncrona se tornem execução síncrona. Ou seja, quando o método start da instância do thread for chamado, este método retornará imediatamente. Se você precisar usar um valor calculado por este thread após chamar o método start, você deve usar o método join. Se você não usar o método join, não há garantia de que quando uma instrução após o método start for executada, o thread será executado. Depois de usar o método join, o programa não continuará a execução até que o thread termine. O código a seguir demonstra o uso de join.
3. Problemas de segurança multithread
Causa do problema: quando várias instruções operam no mesmo thread e compartilham dados, um thread executa apenas parte das múltiplas instruções. Antes da execução ser concluída, outro thread participa da execução, resultando em erros de dados compartilhados.
Solução: Para múltiplas instruções que operam em dados compartilhados, apenas um thread pode ser executado. Durante o processo de execução, outros threads não serão executados.
Bloco de código síncrono:
}
}
}
}
execução nula pública(){
enquanto(verdadeiro){
bilhete de venda();
}
}
}
Comunicação entre threads
x=(x+1)%2;
}
}
}).começar();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
get();
}
}
}).começar();
}
}
/*
Zhang San....Masculino Zhang San....Masculino
lili....nv
lili....masculino Zhang San....nv
lili....masculino
*/
}
}
}).começar();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
sincronizado (p) {
get();
}
}
}
}).começar();
}
}
/*
lili....nv
lili....nv
lili....nv
lili....nv
lili....nv
lili....nv
Zhang San....Masculino Zhang San....Masculino Zhang San....Masculino Zhang San....Masculino
*/
}
}
}).começar();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
sincronizado (p) {
se(!sinalizadores)
tentar {
esperar();
} catch (InterruptedException e) {
// TODO Bloco catch gerado automaticamente
e.printStackTrace();
};
get();
sinalizadores =falso;
p.notifyAll();
}
}
}
}).começar();
}
}
}
Bens finais g =novos Bens();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
g.produce("mercadorias");
}
}
}).começar();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
g.consumir();
}
}
}).começar();
}
}
}
Bens finais g =novos Bens();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
g.produce("mercadorias");
}
}
},"Produtor No.1").start();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
g.produce("mercadorias");
}
}
},"Produtor nº 2").start();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
g.consumir();
}
}
},"Consumidor Nº1").start();
novo Thread(novo Executável(){
execução nula pública(){
enquanto(verdadeiro){
g.consumir();
}
}
},"Consumidor nº 2").start();
}
}
/*
Consumidor nº 2 consumido ****** número do produto: 48049
Produtor Um produzido.... Número do item: 48050
Consumidor nº 1 consumido ****** número do produto: 48050
Produtor Um produzido.... Número do item: 48051
Consumidor nº 2 consumido ****** número do produto: 48051
Produtor No.2 produzido... Número do item: 48052
Consumidor nº 2 consumido ****** número do produto: 48052
Produtor Um produzido.... Número do item: 48053
Consumidor nº 1 consumido ****** número do produto: 48053
Produtor Um produzido.... Número do item: 48054
Consumidor nº 2 consumido ****** número do produto: 48054
Produtor No.2 produzido... Número do item: 48055
Consumidor nº 2 consumido ****** número do produto: 48055
*/