1. O que é uma fila de bloqueio?
Uma fila é uma estrutura de dados que possui duas operações básicas: adicionando um elemento no final da fila e removendo um elemento da cabeça da fila. A diferença entre as equipes de bloqueio e as filas comuns é que as filas comuns não bloquearão o encadeamento atual. Ao enfrentar modelos semelhantes ao produtor de consumidores, estratégias adicionais de sincronização e estratégias de despertar entre thread devem ser implementadas. O uso de uma fila de bloqueio bloqueará o encadeamento atual. Quando a fila estiver vazia, a operação de obtenção de elementos da fila será bloqueada. Quando a fila estiver cheia, a operação de adicionar elementos à fila também será bloqueada.
2. A principal fila de bloqueio e seus métodos
O pacote java.util.Concurrent fornece várias filas principais de bloqueio, principalmente da seguinte forma:
1) ArrayblockingQuee: uma fila de bloqueio com base na implementação da matriz. Ao criar um objeto ArrayBlockingQueue, sua capacidade deve ser especificada. Também pode ser especificado para políticas de acesso. Por padrão, não é justo, ou seja, não garante que o tópico com o tempo de espera mais longo possa acessar a fila primeiro.
2) LinkedBlockingQuee: uma fila de bloqueio com base em uma lista vinculada. Se o tamanho da capacidade não for especificado ao criar um objeto LinkEdBlockingQueue, o tamanho padrão será inteiro.max_value.
3) As duas filas acima são as primeiras filas da primeira saída, mas PriorityBlockingQueue não é. Ele classificará os elementos de acordo com a prioridade dos elementos e dequeue em ordem prioritária. Cada elemento Dequeue é o elemento de prioridade mais alta. Observe que esta fila de bloqueio é uma fila de bloqueio ilimitada, ou seja, não há limite superior na capacidade (você pode saber através do código -fonte que ele não possui um sinalizador de sinal cheio do contêiner). Os dois primeiros tipos são filas limitadas.
4) Atraso: baseado no PriorityQueue, uma fila de bloqueio de atraso. O elemento no atraso pode obter apenas o elemento da fila quando o tempo de atraso especificado é atingido. O detraso também é uma fila ilimitada; portanto, a operação (produtora) de inserção de dados na fila nunca será bloqueada e apenas a operação (consumidor) da obtenção de dados será bloqueada.
As filas de bloqueio incluem a maioria dos métodos em filas não bloqueadores e fornecem vários outros métodos muito úteis:
O método put é usado para armazenar elementos na cauda da fila e, se a fila estiver cheia, espere;
O método de Take é usado para obter elementos da fila e, se a fila estiver vazia, espere;
O método de oferta é usado para armazenar elementos na cauda da fila. Se a fila estiver cheia, ele esperará por um certo tempo. Quando o período for atingido, se a inserção não tiver sido bem -sucedida, ela retornará falsa; Caso contrário, ele retornará verdadeiro;
O método da pesquisa é usado para obter elementos da primeira fila. Se a fila estiver vazia, esperará por um certo tempo. Quando o período for atingido, se for recuperado, retornará nulo; Caso contrário, ele retornará o elemento obtido;
Aqui está um código:
importar java.util.concurrent.arrayblockqueue;/** * @Author Autor: xu jiane-mail: [email protected] * @Version Criado: 20 de março de 2016 às 12:52:53 PM * Class Descrição */public class BlockingQue {public Stoid Maid (String [] java.util.Concurrent.BlockingQueue <String> blockingQueue = new ArrayBlockingQueue <> (5); for (int i = 0; i <10; i ++) {// Adicione o elemento especificado a esta fila BlockingQueue.put ("Adicionar elemento"+i); System.out.println ("Elemento adicionado à fila de bloqueio:" + i); } System.out.println ("O programa termina desta vez e sairá ----"); }}
Quando o número de filas de bloqueio de limite é 5, depois de adicionar 5 elementos, o processo será bloqueado fora da fila e espera, e o programa não termina no momento.
Quando a fila estiver cheia, removemos o elemento do cabeçalho e podemos continuar adicionando elementos à fila de bloqueio. O código é o seguinte:
classe pública BlockingQueue {public static void main (string [] args) lança interruptedException {java.util.concurrent.blockingQueue <String> blockingQueue = new ArrayBlockingQueue <> (5); for (int i = 0; i <10; i ++) {// Adicione o elemento especificado a esta fila BlockingQueue.put ("Adicionar elemento"+i); System.out.println ("Elemento adicionado à fila de bloqueio:" + i); if (i> = 4) System.out.println ("Remova o elemento do cabeçalho" +BlockingQueue.take ()); } System.out.println ("O programa termina desta vez e sairá ----"); }Os resultados da execução são os seguintes:
3. Princípio da implementação do bloqueio da fila <r /> O seguinte analisa principalmente o princípio da implementação do ArrayBlockingQueue.
Primeiro, vamos dar uma olhada nas variáveis membros da aula de ArrayblockingQueue:
classe pública ArrayblockingQueue <e> estende abstratoqueue <e> implementa BlockingQueue <e>, java.io.Serializable { / ** itens de estrutura de armazenamento subjacente* / objeto final []; / ** Subscrito do elemento principal da equipe*/ int TakeIndex; / ** Subscrito do elemento da cauda da equipe*/ int putIndex; / ** Número total de elementos da fila*/ int contagem; / ** Reentrantlock*/ Final ReentrantLock Lock; / ** Notabless Wait Condition*/ condição final privada Notaby; / ** Notfull Wait Condition*/ condição final privada Notfull; /** * Estado compartilhado para iteradores atualmente ativos, ou nulo se houver * conhecido por não ser. Permite que as operações de fila atualizem * o estado do iterador. */ transitório ITRS ITRS = NULL;Como você pode ver, o ArrayBlockockQueue usado para armazenar elementos é na verdade uma matriz.
Vamos dar uma olhada na implementação de dois métodos importantes de ArrayBlockingQueue, put () e Take ():
public void put (e e) lança interruptedException {// Verifique primeiro se e está vazio de checkNotNull (e); // adquire o bloqueio de bloqueio de bloqueio de bloqueio = this.lock; Lock.lockInterruptível (); tente {// Quando a fila estiver cheia, digite a condição e aguarde enquanto (count == items.length) notfull.await (); // A fila não é satisfeita, execute a operação da fila (e); } finalmente {// libere o bloqueio de bloqueio.unlock (); }} Vejamos a operação de união específica:
private void enQueue (e x) {Final Object [] itens = this.items; // itens de entrada [putIndex] = x; if (++ putIndex == items.length) putIndex = 0; // Número total de filas +1 contagem ++; // Selecione um segmento aleatoriamente no conjunto de espera da condição não negligenciada para desbloquear seu estado de bloqueio NotEmpty.Signal (); } Aqui está o código -fonte do método Take ():
public e Take () lança interruptedException {// adquire o bloqueio de bloqueio de reentrantlock bloqueado = this.lock; Lock.lockInterruptível (); tente {// A fila está vazia enquanto (contagem == 0) // o thread se junta à condição notável que espera não o NotEmpty.await (); // não está vazio, saia da fila retornar dequeue (); } finalmente {// libere o bloqueio de bloqueio.unlock (); }} 4. Aplicação de filas de bloqueio: implementando o modelo de produtor consumidor
/** * @Author Autor: Xu Jiane-Mail: [email protected] * @Versão Criada Hora: 20 de março de 2016 às 14:21:55 * Classe Descrição: Modo produtor de consumidor implementado bloqueando a fila */public class Test {private int queuseize = 10; Private ArrayBlockingQueue <Teger> fila = new ArrayBlockingQueue <TEGER> (fila); public static void main (string [] args) {teste test = new test (); Produtor Produtor = Test.New Producer (); Consumidor consumer = test.new consumer (); produtor.start (); consumer.start (); } classe Consumer estende thread {@Override public void run () {consumo (); } private void consumo () {while (true) {tente {fileue.take (); System.out.println ("Pegue um elemento da fila, e a fila permanece" + fila.size () + "elementos"); } catch (interruptedException e) {e.printStackTrace (); }}}} classe Produtor estende Thread {@Override public void run () {Produce (); } private void Produce () {while (true) {tente {Queue.put (1); System.out.println ("Insira um elemento na fila, o espaço restante na fila:"+ (filaeuseize - fila.size ())); } catch (interruptedException e) {e.printStackTrace (); }}}}}}
O exposto acima é tudo sobre este artigo, espero que seja útil para o aprendizado de todos.