Varias formas de implementar problemas de productores y consumidores en Java
El problema productor-consumidor es un problema clásico de subprocesos múltiples. Describe que hay un área de amortiguamiento como almacén. Los productores pueden colocar productos en el almacén y los consumidores pueden sacar productos del almacén.
Los métodos para resolver el problema productor/consumidor se pueden dividir en dos categorías:
Adoptar algún mecanismo para proteger la sincronización entre productores y consumidores;
Crear un conducto entre productor y consumidor.
El primer método es más eficiente y fácil de implementar. El código es más controlable y es un modo de uso común. El segundo tipo de búfer de canalización no es fácil de controlar, el objeto de datos transferido no es fácil de encapsular, etc., y no es muy práctico.
Hay cuatro métodos en Java que admiten la sincronización, los tres primeros son métodos de sincronización y uno es un método de canalización.
Método wait() / notify()
Método await() / signal()
Método de cola de bloqueo BlockingQueue
PipedInputStream / PipedOutputStream
Implementado a través de los métodos wait()/notify():
Los métodos wait()/nofity() son dos métodos de la clase base Object:
método wait(): cuando el búfer está lleno/vacío, el subproceso productor/consumidor detiene su propia ejecución, abandona el bloqueo, se pone en estado de espera y permite que otros subprocesos se ejecuten.
Método notify(): cuando el productor/consumidor pone/saca un producto del búfer, envía una notificación ejecutable a otros subprocesos en espera y, al mismo tiempo, abandona el bloqueo y se pone en un estado de espera.
Logrado mediante los métodos await()/signal():
Las funciones de await() y signal() son básicamente las mismas que wait()/nofity() y pueden reemplácelos, pero están directamente vinculados al mecanismo de bloqueo Lock recientemente introducido, lo que permite una mayor flexibilidad. Al llamar al método newCondition() en el objeto Lock, la variable de condición se vincula a un objeto lock, controlando así la seguridad de los programas concurrentes que acceden a recursos competitivos.
Logrado mediante el método BlockingQueue:
Es una cola que se ha sincronizado internamente y el método de implementación utiliza nuestro segundo método await() / signal(). Puede especificar la capacidad al generar el objeto. Utiliza los métodos put() y take() para bloquear operaciones:
El método put(): similar a nuestro hilo productor anterior, se bloquea automáticamente cuando la capacidad alcanza el máximo.
El método take(): similar a nuestro hilo de consumo anterior, se bloquea automáticamente cuando la capacidad es 0.