How to solve Producer/Consumer problem with ThreadPoolExecutor

Viewed 237

I have set up a short consumer/producer class, maybe already here there are some remarks on improvement potential.

My question is: I have read in some remarks that this should be better done by using a ThreadPoolExecutor. I didn't find out yet how to implement starting and stopping of the consumer/producer thread

import logging
import random
from queue import Queue
from threading import  Thread, Event
from time import sleep


class Updater:
    def __init__(self):
        self.update_queue = Queue(5)
        self._logger = logging.getLogger(__name__)
        self._producer = None
        self._consumer = None
        self.producer_running = Event()
        self.consumer_running = Event()

    def producer(self):
        while self.producer_running.is_set():
            item = random.randint(0, 10)
            self.update_queue.put(item)
            sleep(0.1*float(random.randint(0,10)))

    def consumer(self):
        while self.consumer_running.is_set() or not self.update_queue.empty():
            item = self.update_queue.get()
            sleep(0.2*float(random.randint(0,10)))

    def start(self):
        if not self.producer_running.is_set():
            
            self.producer_running.set()
            self._producer = Thread( target=self.producer)
            self._producer.start()

            self.consumer_running.set()
            self._consumer = Thread( target=self.consumer)
            self._consumer.start()

    def stop(self):
            self.producer_running.clear()
            self._producer.join()

            self.consumer_running.clear()
            self._consumer.join()

if __name__ == "__main__":
    logging.basicConfig(level=logging.INFO,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

    foo = Updater()
    foo.start()
    sleep(5)
    foo.stop()

Update

I've created the stop and start method now with concurrent.futures , it works but I am not sure if that's how it is intended

    self.executor = concurrent.futures.ThreadPoolExecutor(max_workers=5) 

    def start(self):
        if not self.producer_running.is_set():
            
            self.producer_running.set()
            self._producer = self.executor.submit(self.producer)

            self.consumer_running.set()
            self._consumer = self.executor.submit(self.consumer)


    def stop(self):
            self.producer_running.clear()
            concurrent.futures.wait([self._producer])

            self.consumer_running.clear()
            concurrent.futures.wait([self._consumer])
            self.executor.shutdown()
0 Answers
Related