O que é um pool de threads
Um pool de threads é uma coleção de threads que [execução de loop] múltiplas lógica de aplicativo em um ou mais threads.
De um modo geral, os pools de threads têm as seguintes peças:
Um ou mais threads que completam a tarefa principal.
Tópicos de gerenciamento usados para gerenciamento de agendamento.
A fila de tarefas deve ser executada.
A função do pool de threads:
A função de um pool de threads é limitar o número de threads executados no sistema.
Dependendo do ambiente do sistema, o número de threads pode ser definido automaticamente ou manualmente para obter o melhor efeito de operação; Menos recursos do sistema são desperdiçados e mais congestionamento do sistema não é alto. Use um pool de threads para controlar o número de threads e outros threads estão esperando na fila. Depois que uma tarefa é executada, a primeira tarefa é retirada da fila para iniciar a execução. Se não houver processo de espera na fila, esse recurso do pool de threads está esperando. Quando uma nova tarefa precisa ser executada, se houver threads de trabalhadores em espera no pool de threads, ele poderá começar a funcionar; Caso contrário, ele entrará na fila de espera.
Implementar pool de threads sozinho
Com base no entendimento acima do pool de threads, escrevemos nosso próprio pool de threads simples:
Interface simples do pool de threads:
interface pública ThreadPool <Job estende Runnable> {// Executar uma tarefa (Job), este trabalho deve implementar o Execute Void Runnable (emprego); // Fechar o piscina de threads void Shutdown (); // Aumente o fio do trabalhador, ou seja, o thread usado para executar a tarefa vazio de addWorkers (int num); // Reduza o fio do trabalhador Void Remowworker (int num); // Obtenha o número de tarefas esperando para ser executado void getJobsize ();}O cliente pode enviar o trabalho ao pool de threads através do método Execute (Job) para execução, e o cliente não precisa esperar que o trabalho seja executado. Além do método Execute (Job), a interface do pool de threads fornece métodos para aumentar/diminuir os threads do trabalhador e fechar os pools de threads. Cada cliente envia um trabalho que inserirá uma fila de trabalho e aguarde o tópico do trabalhador processar.
A implementação padrão da interface do pool de threads
classe pública DefaultThreadpool <Job estende Runnable> implementa ThreadPool <wob> {// Número máximo de threads para thread manutenção de manutenção thread fhread privado estático final int max_worker_numbers = 10; // Valor padrão do tópico Manutenção do pool Tópico privado estático final int default_worker_numbers = 5; // Número mínimo de thread manutenção de manutenção tópico privado estático final int min_worker_numbers = 1; // Mantenha uma lista de trabalho, que adiciona o trabalho Iniciado pelo Cliente Private Final LinkedList <Job> Jobs = new LinkedList <Job> (); // Lista de threads de trabalhadores LISTA FINAL PRIVADO <Restring> Workers = Coleções.SynchronizedList (New ArrayList <Reward> ()); // Número de tópicos de trabalhadores privados int workernum; // gerar threadnum atômico privado = new atomiclong (); // gerar thread pool public defaultThreadpool () {this.workernum = default_worker_numbers; inicialize trabalhadores (this.workernum); } public defaultThreadpool (int num) {if (num> max_worker_numbers) {this.workernum = default_worker_numbers; } else {this.workernum = num; } inicialize trabalhadores (this.workernum); } // Inicialize cada thread do trabalhador private void inicialize trabalhadores (int num) {for (int i = 0; i <num; i ++) {trabalhador trabalhador = new Worker (); // Adicione à lista de trabalhadores threads Workers.Add (trabalhador); // Inicie o thread do thread do trabalhador thread = novo thread (trabalhador); thread.start (); }} public void Execute (Job Job) {if (job! = null) {// De acordo com o mecanismo "Wait/Notify" do thread, devemos bloquear os trabalhos sincronizados (Jobs) {jobs.addlast (Job); jobs.Notify (); }}} // Feche o pool de threads que deve fechar cada thread de trabalhador public void Shutdown () {for (trabalhador w: trabalhadores) {w.shutdown (); }}} // Adicione Thread Worker public void addworkers (int num) {// Adicione o bloqueio para impedir que o fio aumente ou a conclusão enquanto o próximo fio continua a aumentar, fazendo com que o fio do trabalhador exceda o valor máximo sincronizado (Jobs) {if (num +.workernum> max_worker_numbers) {num = max_work } inicialize trabalhadores (num); this.workernum += num; }} // Reduza o fio do trabalhador public void Remowworker (int num) {Synchronized (Jobs) {if (num> = this.workernum) {lança nova ilegalArgumentException ("excede o número de threads existentes"); } para (int i = 0; i <num; i ++) {trabalhador trabalhador = trabalhadores.get (i); if (trabalhador! = null) {// feche o thread e remova o trabalhador.shutdown (); trabalhadores.remove (i); }} this.workernum -= num; }} public int getJobSize () {// TODO Method Auto-Gerated Stub Return Workers.size (); } // Definir a classe de thread do trabalhador que o trabalhador implementa Runnable {// indica se o trabalhador privado volátil booleano em execução = true; public void run () {while (em execução) {job job = null; // Mecanismo de espera/Notificação de threads sincronizado (Jobs) {if (jobs.isEmpty ()) {try {jobs.wait (); // thread aguarda o wakeup} catch (interruptedException e) {// detecta a operação de interrupção externa no encadeamento e retorna Thread.CurrentThread (). retornar; }} // Retire um trabalho de emprego = jobs.removefirst (); } // Execute o trabalho se (job! = Null) {job.run (); }}} // encerrar o thread public void Shutdown () {Running = false; }}}
A partir da implementação do pool de threads, pode -se observar que, quando o cliente chama o método Execute (Job), ele adicionará constantemente trabalhos aos trabalhos da lista de tarefas, e cada tópico do trabalhador não lerá os trabalhos dos trabalhos para executar. Quando os trabalhos estão vazios, o fio do trabalhador entra no estado de espera.
Depois de adicionar um trabalho, o método notify () é chamado nos trabalhos da fila de trabalho para acordar um tópico de trabalhador. Aqui não chamamos o notifyAll () para evitar desperdiçar recursos movendo todos os threads na fila de espera para a fila de bloqueio.
A essência de um pool de threads é usar uma fila de trabalho à prova de threads para conectar threads trabalhadores e threads de clientes. O encadeamento do cliente retorna depois de colocar a tarefa na fila de trabalho, enquanto o thread trabalhador mal pega o trabalho da fila de trabalho e a executa. Quando a fila de trabalho está vazia, o tópico do trabalhador entra no estado de espera. Quando um cliente envia uma tarefa, ele passa por qualquer tópico do trabalhador. Com o envio de um grande número de tarefas, mais threads de trabalhadores são despertados.
Referência: "A arte da programação simultânea em Java" Fang Tengfei