Condition notify を使ったスレッドの制御

threading.Condition と、条件となる任意のオブジェクトをグローバル変数スコープにして
実現させます。
以下、サンプル

# -*- coding: utf-8 -*-
from threading import Thread, Condition
import time

# 生成格納先リスト
products = []
# 条件オブジェクトの作成
condition = Condition()

# Producer スレッド
class Producer(Thread):
    def run(self):
        global products
        global condition
        while True:
            with condition:
                if len(products) == 0:
                    print('Producer: product append')
                    products.append(1)
                    condition.notify()
            time.sleep(2)
# Consumer スレッド
class Consumer(Thread):
    def run(self):
        global products
        global condition
        while True:
            with condition:
                if len(products) > 0:
                    print('Consumer: product pop')
                    products.pop(0)
                else:
                    print('No product --> Wait')
                    condition.wait()
            time.sleep(2)
# スレッドの生成
producer_thread = Producer()
consumer_thread = Consumer()
# スレッドの開始
producer_thread.start()
consumer_thread.start()

重要なのは、
Condition の ロックの取得(acquire) と解放(release) をする with ブロックの中で、
・notify や wait を行うこと。
 → with ブロックの中で wait になる条件を問い合わせる。

notify 通知 → wait()
結果

Producer: product append
Consumer: product pop
No product --> Wait
Producer: product append
Consumer: product pop
Producer: product append
Consumer: product pop
Producer: product append
Consumer: product pop
Producer: product append
Consumer: product pop
No product --> Wait
Producer: product append
Consumer: product pop

notify() は、notify_all() の他に、notify(n) と通知する数=nを指定できるが、
マニュアルにはこう書いてある。
threading — Thread-based parallelism — Python 3.11.5 documentation

This method wakes up at most n of the threads waiting for the condition variable; it is a no-op if no threads are waiting.

The current implementation wakes up exactly n threads, if at least n threads are waiting. However, it’s not safe to rely on this behavior. A future, optimized implementation may occasionally wake up more than n threads

待機しているスレッド n個までを起動できるとなっているが、
However, it’s not safe to rely on this behavior. A future, optimized implementation may occasionally wake up more than n threads
こう書かれていると躊躇します。

準備するCondition 毎に、wait() するスレッド、notify() するスレッドを管理することになります。