Q:

Динамическое создание и завершение потоков

К, примеру, есть код:  
import threading
from time import sleep

class MyThread(threading.Thread):
    def __init__(self, key):
        super(MyThread, self).__init__()
        self.daemon = True
        self.key = key
        self.start()

    def run(self):
        while True:
            print('thread', self.key)
            sleep(1.5)

threads = dict()

def add_thread(key):
    key = int(key)
    if threads.get(key) is None:
        threads[key] = MyThread(key)

def del_thread(key):
    key = int(key)
    if threads.get(key) is not None:
        thread = threads.pop(key, None)
        if thread is not None:
            # тут, что-то, что освободит поток
            print('остановка', key)

i = 0
while True:
    add_thread(i)
    i += 1
    if i >= 10:
        del_thread(i - 10)
    sleep(1)

Код динамически добавляем потоки, но так же нужно динамически их и останавливать, как это сделать в данном примере?

A:

Замените while True: на while not self.stopped.wait(1.5):.. (уберите time.sleep(1.5)), где self.stopped = threading.Event(), тогда чтобы остановить поток, вызовите thread.stopped.set() (поток выйдет на wait() вызове, не дожидаясь пока 1.5 секунды закончатся).
Код в вопросе можно упростить: чтобы запускать новый поток каждую секунду и останавливать  его через десять итераций:
#!/usr/bin/env python3
import collections
import logging
import time
import threading

def worker(stopped):
    while not stopped.wait(1.5):
        logging.info("heartbeat")

logging.basicConfig(level=logging.INFO,
    format="%(relativeCreated)d %(threadName)s %(message)s")
events = collections.deque(maxlen=10)
while True:
    events.append(threading.Event())
    threading.Thread(target=worker, args=[events[-1]], daemon=True).start()
    if len(events) == 10:
        events.popleft().set()  # stop 10th thread from the end
    time.sleep(1 - time.monotonic() % 1) # every second 

Подробнее об этом time.sleep() вызове см. Как правильно сделать временный цикл?

