Как реализовать правильный порядок выполнения потоков в python?

Недавно начал изучать треды в питоне, и столкнулся с такой проблемой: мне нужно, чтобы функция "два" заканчивала выполнение после выполнения функции один в треде, но метод соединения не работает, видимо из-за цикла while true в третья функция. Я пытался использовать очередь, но это тоже не сработало.

Сам код:

from threading import Thread,Event

def one():
    event.set()
    thr.join()
    for i in range(3):
        print('some print')
        time.sleep(1)

def two():
    t = Thread(target=one)
    t.start()
    #with t.join() here the program does not work at all, same thing with event.set()
    print('func two finished')

def three(callback, event):
    c = 0
    while True:
        c += 1
        time.sleep(1)
        print('func 3 is working')
        if c == 5:
            two()
        if event.is_set():
            callback(c)
            print('func 3 is stopped')
            break

def callback(t):
    print('callback ',t)

def thread(callback):
    global event, thr
    event = Event()
    thr = Thread(target=three, args=(callback, event,))
    thr.start()
    thr.join()

thread(callback)

Текущий выход:

func 3 is working
func 3 is working
func 3 is working
func 3 is working
func 3 is working
func two finished
callback  5
func 3 is stopped
some print
some print
some print

Ожидал:

func 3 is working
func 3 is working
func 3 is working
func 3 is working
func 3 is working
callback  5
func 3 is stopped
some print
some print
some print
func two finished
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Как подобрать выигрышные акции с помощью анализа и визуализации на Python
Отказ от ответственности: Эта статья предназначена только для демонстрации и не должна использоваться в качестве инвестиционного совета.
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
Потяните за рычаг выброса энергососущих проектов
Потяните за рычаг выброса энергососущих проектов
На этой неделе моя команда отменила проект, над которым я работал. Неделя усилий пошла насмарку.
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Библиотека для работы с мороженым
Библиотека для работы с мороженым
Лично я попрощался с операторами print() в python. Без шуток.
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Эмиссия счетов-фактур с помощью Telegram - Python RPA (BotCity)
Привет, люди RPA, это снова я и я несу подарки! В очередном моем приключении о том, как создавать ботов для облегчения рутины. Вот, думаю, стоит...
1
0
61
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Нужная вам последовательность получается небольшой перестановкой команд. Но непонятно, зачем нужны потоки, если все делается последовательно.

from threading import Thread, Event
import time


def one(event):
    event.set()
    for i in range(3):
        print('some print')
        time.sleep(1)


def two(event):
    t = Thread(target=one, args=(event,))
    t.start()
    t.join()
    print('func two finished')


def three(event):
    c = 0
    while True:
        c += 1
        time.sleep(1)
        print('func 3 is working')
        if c == 5:
            callback(c)
            print('func 3 is stopped')
            two(event)
            break


def callback(t):
    print('callback ', t)


def thread():
    event = Event()
    thr = Thread(target=three, args=(event,))
    thr.start()


thread()

--------------------------------

func 3 is working
func 3 is working
func 3 is working
func 3 is working
func 3 is working
callback  5
func 3 is stopped
some print
some print
some print
func two finished

Это комментарий, а не ответ.


Это не имеет никакого смысла:

    t = Thread(target=one, args=(event,))
    t.start()
    t.join()

Нет смысла начинать новый поток, если вы не собираетесь делать что-то одновременно с этим потоком. Либо сделать это,

    t = Thread(target=one, args=(event,))
    t.start()
    do_something_else_concurrently_with_thread_t(...)
    t.join()

Или просто вызовите функцию вместо создания нового потока для ее вызова:

    one(event)

Если вы не хотите параллелизма, вам не нужны потоки.

Ответ принят как подходящий

Ваша программа создает взаимоблокировку, если вы раскомментируете этот t.join() вызов функции two;

  • Поток thr не может завершиться до тех пор, пока не завершится поток t, потому что поток thr вызывает t.join() в функции two.

  • Поток t не может завершиться до тех пор, пока не завершится поток thr, потому что поток t вызывает thr.join() в функции one.

Ни один поток не может завершиться до тех пор, пока не завершится другой поток. Следовательно, ни один поток никогда не может завершиться.


Почему one присоединился к теме thr?

def one():
    event.set()
    thr.join()           # What were you trying to do here?
    for i in range(3):
        print('some print')
        time.sleep(1)

Ваша программа выдаст желаемый результат, если вы закомментируете этот вызов соединения и раскомментируете вызов t.join() в функции two.

После запуска кода я понимаю, что «не работает» вы имеете в виду, что программа завершена до того, как все отпечатки будут напечатаны. Причина в том, что вы присоединяетесь к thr треду дважды, один из них к основному треду. Последовательность возврата соединения не гарантируется. Когда основной поток завершается, все потоки, созданные программой, также завершаются, поэтому они завершаются несмотря ни на что.

То же самое при установке события, оно заставляет основной поток выйти и убить оставшиеся потоки.

Чтобы сделать то, что вы намереваетесь, вы должны дождаться одного потока в основном потоке.

from threading import Thread,Event

def one():
    event.set()
    thr.join()
    for i in range(3):
        print('some print')
        time.sleep(1)

def two():
    t = Thread(target=one)
    t.start()
    #with t.join() here the program does not work at all, same thing with event.set()
    print('func two finished')

def three(callback, event):
    c = 0
    while True:
        c += 1
        time.sleep(1)
        print('func 3 is working')
        if c == 5:
            two()
        if event.is_set():
            callback(c)
            print('func 3 is stopped')
            break

def callback(t):
    print('callback ',t)

def thread(callback):
    global event, thr
    event = Event()
    thr = Thread(target=three, args=(callback, event,))
    thr.start()
    thr.join()

thread(callback)

Обратите внимание, что, как уже было сказано, это может быть полезно для изучения целей, но его необходимо изменить, если вы действительно хотите использовать его в реальном коде.

Другие вопросы по теме