Compartir tecnología

[Sistema operativo] Cola de bloqueo y modelo productor-consumidor

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

cola de bloqueo

1. Concepto

La cola de bloqueo es un tipo especial de cola que también sigue el principio de "primero en entrar, primero en salir".

La cola de bloqueo puede ser una estructura de datos segura para subprocesos y tiene las siguientes características:

  • Cuando la cola está llena, continuar ingresando a la cola se bloqueará hasta que otros subprocesos tomen elementos de la cola..
  • Cuando la cola está vacía, continuar quitando la cola también se bloqueará hasta que otros subprocesos inserten elementos en la cola.

Un escenario de aplicación típico de cola de bloqueo es el "modelo productor-consumidor". Este es un modelo de desarrollo muy típico.
productor

El modelo de consumidor resuelve el fuerte problema de acoplamiento entre productores y consumidores a través de un contenedor.

Los productores y consumidores no se comunican directamente entre sí, sino que se comunican a través de colas de bloqueo. Por lo tanto, una vez que el productor produce los datos, no necesita esperar a que el consumidor los procese, sino que los arroja directamente a la cola de bloqueo. no solicita datos al productor, sino que se obtienen directamente de la cola de bloqueo.

Hay dos pasos principales en la implementación del modelo productor-consumidor:

  1. productor de implementos
  2. darse cuenta del consumidor

2. Cola de bloqueo en la biblioteca estándar.

Hay una cola de bloqueo integrada en la biblioteca estándar de Java. Si necesitamos usar colas de bloqueo en algunos programas, podemos usar directamente la cola de bloqueo en la biblioteca estándar.
Poder.

  • BlockingQueue es una interfaz. La clase de implementación real es LinkedBlockingQueue.
  • El método put se utiliza para bloquear la entrada a la cola y el método take se utiliza para bloquear la salida de la cola.
  • BlockingQueue también tiene métodos como oferta, encuesta y vistazo, pero estos métodos no tienen características de bloqueo.

El pseudocódigo para bloquear la cola es el siguiente:

BlockingQueue<String> queue = new LinkedBlockingQueue<>();

// ⼊队列
queue.put("abc");

// 出队列. 如果没有 put 直接 take, 就会阻塞.
String elem = queue.take();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

3. Modelo productor-consumidor

public static void main(String[] args) throws InterruptedException {

	BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<Integer>();
	
	Thread customer = new Thread(() -> {
		while (true) {
			try {
				int value = blockingQueue.take();
				System.out.println("消费元素: " + value);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}, "消费者");
	
customer.start();

	Thread producer = new Thread(() -> {
		Random random = new Random();
		while (true) {
			try {
				int num = random.nextInt(1000);
				System.out.println("生产元素: " + num);
				blockingQueue.put(num);
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}, "生产者");
	
	producer.start();
	customer.join();
	producer.join();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

4. Implementación de la cola de bloqueo

  1. Esto se logra mediante el método de "cola circular".
  2. Utilice sincronizado para controlar el bloqueo.
  3. Cuando put inserta elementos, determina si la cola está llena y espera (tenga en cuenta que la espera debe realizarse en un bucle. Cuando se despierta, es posible que la cola no esté llena porque se pueden despertar varios subprocesos al mismo tiempo).
  4. Cuando take saca el elemento, determina si la cola está vacía y espera (también es una espera de bucle).
public class BlockingQueue {

	private int[] items = new int[1000];
	private volatile int size = 0;
	private volatile int head = 0;
	private volatile int tail = 0;
	
	public void put(int value) throws InterruptedException {
		synchronized (this) {
		// 此处最好使⽤ while.
		// 否则 notifyAll 的时候, 该线程从 wait 中被唤醒,
		// 但是紧接着并未抢占到锁. 当锁被抢占的时候, 可能⼜已经队列满了
		// 就只能继续等待
			while (size == items.length) {
				wait();
			}
			items[tail] = value;
			tail = (tail + 1) % items.length;
			size++;
			notifyAll();
		}
	}
	
	public int take() throws InterruptedException {
		int ret = 0;
		synchronized (this) {
			while (size == 0) {
				wait();
			}
			ret = items[head];
			head = (head + 1) % items.length;
			size--;
			notifyAll();
		}
		return ret;
	}
	
	public synchronized int size() {
		return size;
	}
	
	// 测试代码
	public static void main(String[] args) throws InterruptedException {
		BlockingQueue blockingQueue = new BlockingQueue();
		Thread customer = new Thread(() -> {
		while (true) {
			try {
				int value = blockingQueue.take();
				System.out.println(value);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}, "消费者");	
	
		customer.start();
		Thread producer = new Thread(() -> {
			Random random = new Random();
				while (true) {					try {
						blockingQueue.put(random.nextInt(10000));
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}, "生产者");
			
		producer.start();
		customer.join();
		producer.join();
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71

Resumir

  1. La cola de bloqueo es equivalente a un búfer, que equilibra las capacidades de procesamiento de productores y consumidores (recorte y llenado de picos).
  2. El bloqueo de colas también puede desacoplar a productores y consumidores.