1. Tópicos e processos
1. Qual é a diferença entre encadeamento e processo:
Um encadeamento refere -se a uma unidade de execução que pode executar o código do programa durante a execução. No idioma java, os threads têm quatro estados: corra, prontos, suspenda e final.
Um processo refere -se a um programa que está sendo executado. Os tópicos também se tornam processos leves quando têm algo a fazer. Eles têm a menor unidade de execução do programa. Um processo pode ter vários threads. Cada encadeamento compartilha o espaço de energia interno do programa (segmentos de código, segmentos de dados e espaço de heap) e alguns recursos no nível do processo (como arquivos abertos), mas cada thread tem seu próprio espaço.
2. Por que usar multiprocess ? <r /> Existem principalmente os seguintes aspectos no nível do sistema operacional:
- O uso de lreading múltiplo pode reduzir o tempo de resposta do programa. Se uma operação for demorada ou ficar presa em uma longa espera, o programa não responderá a operações como mouse e teclado. Após o uso de múltiplas threading, esse encadeamento demorado pode ser alocado para um encadeamento separado para execução, tornando o programa melhor interatividade.
- A criação de threads e a sobrecarga de comutação são mais baratos em comparação com os processos, enquanto o multithreading é muito eficiente no compartilhamento de dados.
-Computadores multi-CPU ou multi-core têm a capacidade de executar vários threads. Se um único processo for usado, os recursos do computador não serão reutilizados, resultando em um enorme desperdício de recursos. O uso de multithreading em computadores multi-CPU pode melhorar a utilização da CPU.
- O uso do multithreading pode simplificar a estrutura do programa e facilitar o entendimento e a manutenção.
2. Criando threads <r /> geralmente existem três métodos para implementação de multi-threads, e os dois primeiros são os métodos mais usados:
1. Herde a classe de threads e substitua o método run ()
O encadeamento é essencialmente uma instância que implementa a interface executável. Deve-se notar que, depois de chamar o método START (), ele não executa o código multi-thread imediatamente, mas faz com que o thread seja executado. Quando a execução do código multithread é determinado pelo sistema operacional.
Aqui estão as principais etapas:
(1) Defina a subclasse da classe Thread e substitua o método de execução da classe. O corpo do método do método de execução representa a tarefa que o encadeamento deseja concluir. Portanto, o método run () é chamado de órgão de execução.
(2) Crie uma instância da subclasse do encadeamento, ou seja, crie um objeto Thread.
(3) Ligue para o método start () do objeto Thread para iniciar o thread.
public class TestThread estende thread {public void run () {System.out.println ("Hello World"); } public static void main (string [] args) {thread mthread = new testThread (); mthread.start (); }} 2. Implemente a interface executável e implemente o método run () da interface
Aqui estão as principais etapas:
(1) Personalize a classe e implemente a interface executável e implemente o método run ().
(2) Crie uma instância da subclasse do encadeamento e instancie o objeto Thread com o objeto que implementa a interface executável como um parâmetro.
(3) Método Start () Start () de Ligue para iniciar o thread.
public class TestRunnable implementa Runnable {public void run () {System.out.println ("Hello World"); }} classe pública testRunnable {public static void main (string [] args) {testRunnable mTestRunnable = new testRunnable (); Thread mthread = novo thread (mtestrunnable); mthread.start (); }} 3. Implemente a interface chamada e substitua o método Call ()
A interface chamada é na verdade uma classe funcional na estrutura do executor. A interface chamada é semelhante à interface executável, mas fornece funções mais poderosas do que o Runnable, que são manifestadas principalmente nos 3 pontos a seguir:
(1) Callable pode fornecer um valor de retorno após a aceitação da tarefa, e o Runnable não pode fornecer essa função.
(2) O método Call () em Callable pode lançar exceções, enquanto o método Run () do Runnable não pode lançar exceções.
(3) A execução chamável pode obter um objeto futuro. O objeto futuro representa o resultado do cálculo de Ibrahimovic e ele fornece um método para verificar se o cálculo é concluído. Como o encadeamento pertence a um modelo de cálculo assíncrono, é impossível obter o valor de retorno da função de outros threads. Nesse caso, o futuro pode ser usado para monitorar o método Call () quando o thread de destino chama o método Call (). No entanto, quando o método Get () Get () é chamado para obter o resultado, o encadeamento atual bloqueará e saberá o resultado de retorno do método Call ().
classe pública TestCallable {// Crie classes de thread clem estática estática mytestcallable implementos chamáveis {public string Call () lança exceção {retun "hello world"; }} public static void main (string [] args) {myTestCallable mmytestCallable = new MyTestCallable (); ExecutorService mexecutorService = executores.NewsingleThreadpool (); Futuro mfuture = mexecutorService.submit (mmytestcallable); tente {// aguardando o thread termine e retorne o resultado System.out.println (mfuture.get ()); } catch (Exceção e) {e.printStackTrace (); }}}O resultado da saída do programa acima é: Hello World
Entre esses três métodos, geralmente é recomendável implementar a interface executável. O motivo é: primeiro, a classe Thread define uma variedade de métodos que podem ser reescritos por classes derivadas, mas apenas o método run () deve ser reescrito, que realiza a principal função deste thread, que também é o método necessário para implementar a interface executável. Em segundo lugar, uma classe deve ser herdada quando precisar ser fortalecida ou modificada. Portanto, se não houver necessidade de substituir outros métodos da classe Thread, é melhor implementar a interface executável nesse caso.
3. Tópico de interrupção <Br /> O encadeamento será encerrado quando o método Run () RUN () for executado a última instrução no corpo do método e retorna executando a instrução Return, ou quando uma exceção que não é capturada no método não é capturada. Havia um método de parada nas versões anteriores do Java, que outros threads poderiam chamar para encerrar o thread, mas esse método agora foi obsoleto.
O método de interrupção pode ser usado para solicitar o término do thread. Quando um encadeamento chama o método de interrupção, o estado de interrupção do encadeamento será definido. Esta é a bandeira booleana que nenhum thread possui. Cada encadeamento deve verificar esse sinalizador de tempos em tempos para determinar se o thread é interrompido.
Para descobrir se o thread está definido, você pode ligar para o thread.currentThread (). IsInterrupted ():
while (! thread.currentThread (). isInterrupted ()) {faça algo} No entanto, se um thread for bloqueado, o estado de interrupção não poderá ser detectado. É aqui que a interrupção é gerada. Quando um método de interrupção é chamado em um encadeamento bloqueado (chamado de sono ou espera). A chamada de bloqueio será interrompida pela InterruptedException.
Se o método do sono (ou outro método interrompível) for chamado após cada iteração, a detecção interrompida é desnecessária e inútil. Se o método do sono for chamado quando o estado de interrupção for definido, ele não dormirá, mas limpará o estado e lançará uma interrupção. Portanto, se você ligar para o sono em um loop, não detecte o status de interrupção, basta pegar a InterruptedException.
Em muitos códigos publicados, você descobrirá que a InterruptedException é suprimida em um nível muito baixo:
void myTask () {... tente {Sleep (50)} Catch (interruptedException e) {...}}Não faça isso. Se você não acha que há algum benefício em uma captura, há duas opções razoáveis:
Ligue para Thread.CurrentThread (). Interrup () em Catch para definir o estado de interrupção. Os chamadores podem detectá -lo. Uma opção melhor é usar o Throw InterruptedException para marcar seu método, sem usar os blocos de instrução Try para capturar o concluído. Dessa forma, o chamador pode pegar esta exceção:
void myTask () Throw InterruptException {Sleep (50)}4. O estado do tópico
(1). Novo status (novo): um novo objeto de thread é criado.
(2). Estado pronto (Runnable): Depois que o objeto Thread for criado, outros threads chamam o método START () do objeto. O tópico deste estado está localizado no pool de threads executáveis e se torna executável, esperando para obter os direitos de uso da CPU.
(3). Estado em execução: o thread no estado pronto adquire a CPU e executa o código do programa.
(4). Estado bloqueado: Estado bloqueado significa que o encadeamento renuncia aos direitos de uso da CPU por algum motivo e para temporariamente a execução. Não é até o encadeamento entrar no estado pronto que ele tem a chance de ir ao estado de corrida. Existem três tipos de bloqueio:
- Esperando para bloquear: o thread em execução executa o método wait (), e a JVM colocará o thread no pool de espera.
- Bloqueio síncrono: quando o thread em execução adquire o bloqueio de sincronização do objeto, se o bloqueio de sincronização for ocupado por outros threads, a JVM colocará o thread no pool de bloqueio.
- Outro bloqueio: quando um thread em execução executa o método Sleep () ou junção () ou emite uma solicitação de E/S, a JVM definirá o thread como um estado de bloqueio. Quando o Sleep () State se estendeu, a junção () esperou que o thread termine ou o tempo de tempo ou o processamento de E/S tenha sido concluído, o thread reinseriu para o estado pronto.
(5). Estado morto: o thread terminou de executar ou sair do método run () devido a uma exceção, e o thread termina seu ciclo de vida.
5. Prioridade do thread e tópico daemon
1. Prioridade do thread
Em Java, cada thread tem uma prioridade e, por padrão, um thread herda a prioridade de sua classe pai. Você pode usar o método SetPriority para aumentar ou diminuir qualquer prioridade do encadeamento. A prioridade pode ser definida como qualquer valor entre min_priority (definido como 1 na classe Thread) e max_priority (definido como 10 na classe Thread). A prioridade padrão dos threads é Norm_Priority (definida como 5 na classe Thread).
Tente não confiar na prioridade. Se você realmente deseja usá -lo, deve evitar um erro comum que os iniciantes cometem. Se vários encadeamentos de alta prioridade não entrarem no estado inativo, os encadeamentos de baixa prioridade podem nunca ser executados. Sempre que o agendador decidir executar um novo thread, ele seleciona primeiro entre os threads com prioridade, embora isso fome completamente os threads de baixa prioridade.
2. Tópico de daemon
Chamada setDaemon (true); Converte o thread em um fio daemon. O único objetivo dos threads Daemon é fornecer serviços a outros threads. O tópico de tempo é um exemplo. Ele envia sinais para outros threads regularmente ou limpa threads desatualizados que informam itens de cache. Quando apenas os threads Daemon são deixados, a máquina virtual sai, porque se apenas os threads Daemon forem deixados, não há necessidade de continuar executando o programa.
Além disso, a coleta de lixo da JVM, o gerenciamento de memória e outros threads são threads Daemon. Além disso, ao fazer aplicativos de banco de dados, o pool de conexão do banco de dados usado também contém muitos threads em segundo plano, monitorando o número de conexões, tempo de tempo limite, status etc.
O exposto acima é sobre a definição de encadeamento, estado e propriedades do Java Multithreading. Espero que seja útil para o aprendizado de todos.