Este artigo ajuda a dominar o conhecimento básico do Java Multithreading para corresponder aos problemas que você encontrar no futuro. O conteúdo específico é o seguinte
1. Perguntas de entrevista com vários threads java
1. Qual é a diferença entre um processo e um thread?
Um processo é um ambiente de corrida independente, que pode ser considerado um programa ou um aplicativo. Um thread é uma tarefa executada em um processo. O ambiente de tempo de execução do Java é um processo único que contém diferentes classes e programas. Os threads podem ser chamados de processos leves. Os tópicos requerem menos recursos para criar e residir no processo e podem compartilhar recursos no processo.
2. Quais são os benefícios da programação multithread?
Em um programa com vários threads, vários threads são executados simultaneamente para melhorar a eficiência do programa, e a CPU não entrará em um estado ocioso porque um determinado thread precisa aguardar os recursos. Vários threads compartilham a memória do Heap, portanto, criar vários threads para executar algumas tarefas é melhor do que criar vários processos. Por exemplo, os servlets são melhores que o CGI porque os servlets suportam multithreading enquanto o CGI não.
3. Qual é a diferença entre os threads do usuário e os threads Daemon?
Quando criamos um thread em um programa Java, ele é chamado de thread de usuário. Um thread Daemon é um encadeamento que é executado em segundo plano e não bloqueia a JVM terminada. Quando nenhum tópico do usuário está em execução, a JVM fecha o programa e sai. O tópico infantil criado por um thread daemon ainda é um thread daemon.
4. Como criamos um tópico?
Existem duas maneiras de criar threads: um é implementar a interface executável, depois passá -lo para o construtor de threads e criar um objeto Thread; O outro é herdar diretamente a classe Thread. Para obter mais informações, você pode ler este artigo sobre como criar threads em Java.
5. Quais são os diferentes ciclos de vida do fio?
Quando criamos um novo thread em um programa Java, seu status é novo. Quando chamamos o método start () do thread, o estado é alterado para executável. O agendador de threads aloca o tempo da CPU para os threads no pool de threads executáveis e muda seu estado para a execução. Outros estados do fio incluem espera, bloqueados e mortos. Leia este artigo para saber mais sobre o Lifecycles de threads.
6. Posso chamar diretamente o método run () da classe Thread?
Obviamente, mas se chamarmos o método Run () Thread (), ele se comportará o mesmo que o método normal. Para executar nosso código em um novo thread, o método Thread.start () deve ser usado.
7. Como pausar um tópico em execução por um período de tempo?
Podemos usar o método Sleep () da classe Thread para pausar o thread por um período de tempo. Deve -se notar que isso não faz com que o encadeamento termine. Depois que o thread for despertado da hibernação, o estado do thread será alterado para executável e, de acordo com o agendamento do thread, ele será executado.
8. Qual é a sua compreensão da prioridade do tópico?
Cada encadeamento tem prioridade. De um modo geral, os threads de alta prioridade terão prioridade ao executar, mas isso depende da implementação do agendamento de threads, que está relacionado ao sistema operacional (dependente do SO). Podemos definir a prioridade dos threads, mas isso não garante que os threads de alta prioridade sejam executados na frente de threads de baixa prioridade. A prioridade do thread é uma variável int (de 1-10), 1 representa a menor prioridade e 10 representa a maior prioridade.
9. O que são programadores de threads e fatia de tempo?
Um agendador de threads é um serviço de sistema operacional responsável pela alocação de tempo da CPU em threads no estado executável. Depois de criar um thread e iniciá -lo, sua execução depende da implementação do agendador de threads. Sharding de tempo refere -se ao processo de alocar o tempo disponível da CPU para os threads executáveis disponíveis. O tempo alocado da CPU pode ser baseado na prioridade do thread ou no tempo de espera do thread. A programação de threads não é controlada pelas máquinas virtuais Java; portanto, é melhor controlá -lo pelo aplicativo (ou seja, não deixe seu programa depender das prioridades do thread).
10. Em multithreading, o que é truques de contexto?
A mudança de contexto é um processo de armazenamento e restauração do estado da CPU, que permite que a execução do encadeamento retome a execução de pontos de interrupção. A comutação de contexto é um recurso básico dos sistemas operacionais de várias tarefas e ambientes com vários threads.
11. Como você garante que o thread em que o método principal () está localizado é o último thread que termina no programa Java?
Podemos usar o método junta () da classe Thread para garantir que todos os threads criados pelo programa terminem antes da saída do método principal (). Aqui está um artigo sobre o método de junta () da classe Thread.
12. Como os threads se comunicam?
Quando os recursos entre thread podem ser compartilhados, a comunicação entre thread é um meio importante para coordená-los. O método wait ()/notify ()/notifyAll () na classe de objeto pode ser usado para se comunicar entre threads sobre o estado de bloqueios sobre os recursos. Clique aqui para obter mais informações sobre o Thread Wait, notifique e notifiquel.
13. Por que os métodos de comunicação de threads esperam (), notify () e notifyAll () definidos na classe de objeto?
Cada objeto em Java possui um bloqueio (monitor, que também pode ser um monitor) e esperar (), notify () e outros métodos são usados para aguardar o bloqueio do objeto ou notificar outros objetos de encadeamento disponíveis. Não há bloqueios e sincronizadores disponíveis para qualquer objeto usar nos threads java. É por isso que esses métodos fazem parte da classe de objeto, para que todas as classes em Java tenha métodos básicos para comunicação entre thread
14. Por que espera (), notify () e notifyAll () ser chamado em um método de sincronização ou um bloco de sincronização?
Quando um thread precisa chamar o método wait () do objeto, o thread deve ter a trava do objeto. Em seguida, ele libera o bloqueio do objeto e entra no estado de espera até que outros threads chamem o método notify () no objeto. Da mesma forma, quando um thread precisa chamar o método notify () do objeto, ele liberará o bloqueio do objeto para que outros threads aguardem para obter o bloqueio do objeto. Como todos esses métodos requerem threads para manter a trava do objeto, eles só podem ser implementados por meio de sincronização, para que só possam ser chamados no método de sincronização ou no bloco de sincronização.
15. Por que os métodos do sono () e rendimento () da classe de roscas estão estáticos?
Os métodos Sleep () e Caminhamento () da classe Thread serão executados no thread atualmente em execução. Portanto, não faz sentido chamar esses métodos em outros threads que estão em um estado de espera. É por isso que esses métodos são estáticos. Eles podem trabalhar no encadeamento atualmente em execução e evitar a crença equivocada do programador de que esses métodos podem ser chamados em outros threads não executados.
16. Como garantir a segurança do thread?
Existem muitas maneiras de garantir a segurança do encadeamento na sincronização Java, usar classes simultâneas atômicas, implementar bloqueios simultâneos, usar palavras -chave voláteis, usar classes invariantes e classes seguras de threads. Você pode aprender mais no tutorial de segurança do tópico.
17. Qual é o papel da palavra -chave volátil em Java?
Quando usamos a palavra -chave volátil para modificar uma variável, o thread lerá diretamente a variável e não a cache. Isso garante que as variáveis lidas pelo thread sejam consistentes na memória.
18. Qual é a melhor escolha, o método de sincronização ou o bloco de sincronização?
Os blocos síncronos são uma escolha melhor porque não bloqueam o objeto inteiro (e é claro que você também pode deixá -lo bloquear todo o objeto). O método de sincronização bloqueia todo o objeto, mesmo que existam vários blocos de sincronização não relacionados na classe, o que geralmente os leva a parar de executar e precisar esperar para obter o bloqueio no objeto.
19. Como criar um tópico de daemon?
Use o método setDaemon (true) da classe Thread para setDaemon (true) para definir o thread como um thread daemon. Deve -se notar que esse método precisa ser chamado antes de chamar o método start (), caso contrário, uma ilegalthreadStateException será lançada.
20. O que é Threadlocal?
Threadlocal é usado para criar variáveis locais para threads. Sabemos que todos os threads de um objeto compartilharão suas variáveis globais, para que essas variáveis não sejam seguras de threads e possamos usar técnicas de sincronização. Mas quando não queremos usar a sincronização, podemos escolher a variável Threadlocal.
Cada encadeamento terá suas próprias variáveis de encadeamento, que podem usar o método get ()/set () para obter seus valores padrão ou alterar seus valores internamente. As instâncias Threadlocal geralmente querem que elas sejam associadas ao estado do encadeamento como atributos estáticos privados. Neste artigo, você pode ver um pequeno programa sobre threadlocal.
21. O que é grupo de threads? Por que não é recomendado?
ThreadGroup é uma classe cujo objetivo é fornecer informações sobre grupos de threads.
A API do ThreadGroup é relativamente fraca e não oferece mais recursos que o thread. Possui duas funções principais: uma é obter uma lista de threads ativos no grupo de threads; O outro é definir um manipulador de exceção não capturado para threads. No entanto, no Java 1.5, a classe Thread também adicionou o método SetuncaughTexceptionHandler (UNVAGHTEXCECTONDHANDLER EH), para que o grupo ThreadGroup esteja desatualizado e não é recomendável continuar usando -o.
t1.setuncaughtexceptionHandler (new UNNUMPEXCECCETIONHANDLER () {@Override public void UNJUGHTEXCECCECTION (Thread t, Throwable e) {System.out.println ("Exceção ocorreu:"+e.getMessage ());}}); 22. O que é um despejo de thread java e como obtê -lo?
O Thread Dump é uma lista de threads ativos da JVM que são muito úteis para analisar gargalos e impasses do sistema. Existem muitas maneiras de obter despejos de threads - usando o Profiler, Kill -3 Command, Jstack Tool, etc. Prefiro a ferramenta JStack porque é fácil de usar e vem com o JDK. Como é uma ferramenta baseada em terminal, podemos escrever alguns scripts para gerar oportunamente despejos de threads para análise. Leia este documento para saber mais sobre como gerar despejos de threads.
23. O que é um impasse? Como analisar e evitar impasse?
Deadlock refere -se à situação em que mais de dois tópicos estão bloqueados para sempre. Esta situação requer pelo menos dois fios e mais de dois recursos.
Para analisar os deadlocks, precisamos visualizar o despejo de thread do aplicativo Java. Precisamos descobrir esses tópicos com o estado bloqueado e os recursos que estão esperando. Cada recurso tem um ID exclusivo. Usando esse ID, podemos descobrir quais threads já têm seu bloqueio de objeto.
Evitando bloqueios aninhados, usando apenas bloqueios onde são necessários e evitar a espera indefinida são as maneiras usuais de evitar impasses, leia este artigo para aprender a analisar os impasse.
24. Qual é a classe Java Timer? Como criar uma tarefa com um intervalo de tempo específico?
java.util.timer é uma classe de ferramentas que pode ser usada para agendar um thread para executar em um determinado momento no futuro. A classe do temporizador pode ser organizada programando tarefas únicas ou tarefas periódicas.
java.util.timertak é uma classe abstrata que implementa a interface executável. Precisamos herdar essa classe para criar nossas próprias tarefas cronometradas e usar o timer para organizar sua execução.
25. O que é um pool de threads? Como criar um pool de threads java?
Um pool de threads gerencia um conjunto de threads de trabalhadores e também inclui uma fila para colocar tarefas esperando para serem executadas.
java.util.concurrent.executores fornece uma implementação da interface java.util.concurrent.executor para criar pools de threads. O exemplo do pool de threads mostra como criar e usar um pool de threads ou ler o exemplo do ScheduledThreadPoolExector para aprender como criar uma tarefa periódica.
2.
1. O que é operação atômica? Quais classes atômicas existem na API de concorrência Java?
Operação atômica refere -se a uma unidade de tarefa de operação que não é afetada por outras operações. As operações atômicas são necessárias meios para evitar a inconsistência de dados em um ambiente multithread.
Int ++ não é uma operação atômica; portanto, quando um thread lê seu valor e adiciona 1, outro thread pode ler o valor anterior, o que levantará um erro.
Para resolver esse problema, é necessário garantir que a operação de adição seja atômica e poderíamos usar a tecnologia de sincronização para fazer isso antes do JDK1.5. Para JDK1.5, o pacote java.util.concurrent.atomic fornece INT e longos tipos de classes de carregamento, que podem garantir automaticamente que sejam atômicas para suas operações e não requerem sincronização.
2. Qual é a interface de bloqueio na API de concorrência Java? Quais são as vantagens de comparar a sincronização?
A interface de bloqueio fornece uma operação de bloqueio mais escalável do que o método de sincronização e o bloco de sincronização. Eles permitem estruturas mais flexíveis, podem ter propriedades completamente diferentes e podem suportar objetos condicionais de várias classes relacionadas.
Suas vantagens são:
Ele pode tornar o bloqueio mais justo, para que o thread responda a interrupções enquanto aguarda a trava, para que o thread possa tentar adquirir a fechadura e retornar imediatamente quando não puder adquirir o bloqueio ou aguardar um período de tempo, que pode ser adquirido e liberado em diferentes ordens em diferentes intervalos.
3. Qual é a estrutura dos executores?
A estrutura do executor é introduzida no Java 5 com o java.util.concurrent.executor Interface. A estrutura do Executor é uma estrutura que executa tarefas assíncronas que executam chamadas, cronogramas, executa e controla de acordo com um conjunto de políticas.
Os threads de criação ilimitados podem causar excesso de memória do aplicativo. Portanto, a criação de um pool de threads é uma solução melhor porque o número de threads pode ser limitado e o número de threads pode ser reciclado e reutilizado. O uso da estrutura dos executores pode criar facilmente um pool de threads. Leia este artigo para saber como usar a estrutura do executor para criar um pool de threads.
4. O que é uma fila de bloqueio? Como implementar um modelo produtor-consumidor usando filas de bloqueio?
O recurso de java.util.Concurrent.BlockingQueue é: Quando a fila está vazia, a operação de obtenção ou exclusão de elementos da fila será bloqueada ou quando a fila estiver cheia, a operação de adicionar elementos à fila será bloqueada.
A fila de bloqueio não aceita valores nulos e, quando você tenta adicionar valores nulos à fila, ele lança uma NullPointerException.
A implementação de filas de bloqueio é segura para roscas e todos os métodos de consulta são atômicos e usam bloqueios internos ou outras formas de controle simultâneo.
A interface BlockingQueue faz parte da estrutura de coleções Java, que é usada principalmente para implementar problemas de consumidor do produtor.
5. O que é chamável e futuro?
O Java 5 apresenta a interface Java.util.Concurrent.Lable no pacote de concorrência. É muito semelhante à interface executável, mas pode retornar um objeto ou lançar uma exceção.
A interface chamada usa genéricos para definir seu tipo de retorno. A classe Executores fornece alguns métodos úteis para executar tarefas dentro de um chamável em um pool de threads. Como a tarefa chamada é paralela, precisamos esperar o resultado que ele retorna. O objeto java.util.Concurrent.Future resolve esse problema para nós. Depois que o pool de threads envia a tarefa chamada, um objeto futuro é retornado. Usando -o, podemos conhecer o status da tarefa chamada e obter o resultado da execução retornado pelo chamável. O Future fornece um método get () que nos permite aguardar o encerramento do chamável e obtenha seu resultado de execução.
6. O que é FutureTask?
O FutureTask é uma implementação básica do futuro, podemos usá -lo com os executores para lidar com tarefas assíncronas. Normalmente, não precisamos usar a classe FutureTask, ela se torna muito útil apenas quando planejamos reescrever alguns métodos da interface futura e manter a implementação básica original. Podemos apenas herdar e reescrever os métodos de que precisamos.
7. Qual é a implementação de contêineres simultâneos?
Todas as classes de coleta Java falham rapidamente, o que significa que, quando o conjunto é alterado e um thread usa o iterador para atravessar o conjunto, o método Next () do iterador () lançará uma exceção concorrente de exceção.
Os contêineres simultâneos suportam atualizações de travessia e simultânea simultâneas.
As principais classes são simultaneamente, copywritearraylist e copywritearrayset. Leia este artigo para saber como evitar o ConcurrentModificationException.
8. Qual é a classe dos executores?
Os executores fornecem alguns métodos de ferramentas para o Executor, ExecutorService, ScheduledExecutorService, ThreadFactory e Classion Classes.
Os executores podem ser usados para criar convenientemente pools de threads.
De fato, existem muitas outras perguntas básicas da entrevista em Java e você pode organizá -las sistematicamente.
Espero que todos tenham sucesso na entrevista!