Я хочу использовать пакет потоков для вычисления квадрата числа и моего кода, например,
import threading
def my_squr(num): #if this function take long time to run
print(num*num)
return num*num
if __name__ == "__main__":
l1 = [1,3,5,7,11,13,15,17]
for i, item in enumerate(l1):
if i % 3 == 0:
t1 = threading.Thread(target=my_squr, args=(item,))
t1.start()
t1.join()
elif i % 3 == 1:
t2 = threading.Thread(target=my_squr, args=(item,))
t2.start()
t2.join()
else:
t3 = threading.Thread(target=my_squr, args=(item,))
t3.start()
t3.join()
# t1.join()
# t2.join()
# t3.join()
print("Done")
Однако я не понимаю, куда мне поместить метод join()
. Хотя они оба получают одинаковый ответ, я думаю, между ними есть некоторые различия.
Отвечает ли это на ваш вопрос? Какая польза от join() в многопоточности Python?
@ luk2302 luk2302 спасибо за ваш ответ, я все еще не понимаю этот метод после прочтения веб-сайта, означает ли это, что метод соединения не имеет смысла, соединение предназначено только для того, чтобы сделать код понятным?
Если вы присоединяетесь сразу после запуска потока, это означает, что вы ждете, пока он выполнится. Однако это ничем не отличается от обычного вызова функции внутри основного потока. Предположим, что работа функций занимает немного времени, и вам нужно обрабатывать их одновременно. Затем вы можете запустить их и раскомментировать соединения. Это ваш текущий рабочий процесс фрагмента кода
->Create thread x and start
->wait for finish of thread x
->Create thread y and start
->wait for finish of thread y
... and so on.
Однако, если вы измените комментарии к соединениям, это будет новый рабочий процесс.
->Create thread x and start
->Create thread y and start
->Create thread z and start
...
at the end
->wait thread x to finish
->wait thread y to finish
...
Так что здесь, даже когда вы ждете завершения X, ваши другие потоки, такие как y и z, все еще обрабатывают то, что вы делаете внутри.
Обновлено: Вы должны удалить соединения сразу после начала и раскомментировать потоки, которые были в конце. Это было бы более уместно. Кроме того, поскольку процессоры достаточно быстры, чтобы выполнить простую математику всего за миллисекунду, вы не почувствуете никакой разницы.
Где вы должны использовать соединения, полностью зависит от вашей программы. Для вашей ситуации использование в конце, вероятно, было бы лучшим.
Однако предположим, что у вас будет другой поток с именем X_2, который будет использовать результат потока X_1. Затем, прежде чем создавать поток X_2, вы должны присоединиться к потоку X_1.
еще раз спасибо, вы имели в виду, что нигде не нужно добавлять join
? извините, я все еще в замешательстве, если my_squr
выполняется долго, какой из них правильный?
В вашей ситуации использование в конце было бы правильным
@4daJKong, Re, "... нигде не нужно добавлять соединение?" t.join()
— это то, как один поток может дождаться окончания другого потока. Если поток t
что-то делает, и *ЕСЛИ* в каком-то другом потоке u
есть точка, за которой u
не следует продолжать, пока t
не выполнит свою задачу, тогда поток u
может вызвать t.join()
в этой точке, и вызов соединения не вернется до тех пор, пока тред t
сделал свое дело.
@4daJKong, в вашем примере последнее, что делает ваш основной поток, это print("done")
. Если вы не хотите, чтобы это произошло до тех пор, пока не будут выполнены другие три потока, вы можете убедиться, что основной поток join()
все эти другие потоки, прежде чем он напечатает сообщение «Готово».
Вы можете создать список потоков, а затем присоединиться к ним после завершения цикла:
import threading
def my_squr(num): #if this function take long time to run
print(num*num)
return num*num
if __name__ == "__main__":
threads = []
l1 = [1,3,5,7,11,13,15,17]
for i, item in enumerate(l1):
if i % 3 == 0:
t1 = threading.Thread(target=my_squr, args=(item,))
t1.start()
threads.append(t1)
elif i % 3 == 1:
t2 = threading.Thread(target=my_squr, args=(item,))
t2.start()
threads.append(t2)
else:
t3 = threading.Thread(target=my_squr, args=(item,))
t3.start()
threads.append(t3)
for thread in threads:
thread.join()
print("Done")
спасибо за ваш ответ, основная проблема в том, что я не знаю, где я должен добавить join
, в цикле или вне цикла, потому что они оба возвращают один и тот же результат, но я хочу использовать многопоточность
Соединение в моем ответе находится вне цикла, т. Е. Это операция очистки. Мне интересно узнать, что будет делать ваша долговременная функция. Я надеюсь, что это не будет интенсивно использовать процессор, потому что если это так, многопоточность не будет хорошим вариантом.
Присоединение просто останавливает завершение приложения до завершения потока.
Итак, вы хотите присоединиться к темам ПОСЛЕ того, как они начались.
import threading
def my_squr(num): #if this function take long time to run
print(num*num)
return num*num
if __name__ == "__main__":
threads = list()
l1 = [1,3,5,7,11,13,15,17]
for i, item in enumerate(l1):
if i % 3 == 0:
t1 = threading.Thread(target=my_squr, args=(item,))
threads.append(t1)
t1.start()
elif i % 3 == 1:
t2 = threading.Thread(target=my_squr, args=(item,))
threads.append(t2)
t2.start()
else:
t3 = threading.Thread(target=my_squr, args=(item,))
threads.append(t3)
t3.start()
for t in threads:
t,join()
print("Done")
спасибо за ваш ответ, основная проблема в том, что я не знаю, где я должен добавить join
, в цикле или вне цикла, потому что они оба возвращают один и тот же результат, но я хочу использовать многопоточность
Re, «присоединиться... останавливает приложение». Это вводящее в заблуждение утверждение. t.join()
ждет окончания треда t
. Если вам случится вызвать t.join()
из какого-то потока, который вы считаете «приложением», то конечно, присоединение остановит приложение. Но любой поток может присоединиться к любому другому потоку. Самое простое объяснение того, что делает соединение, — это объяснение того, как оно ведет себя в любой ситуации. t.join()
ничего не делает. Он продолжает ничего не делать, пока поток t
не завершится, а затем возвращается.
Без join
ваше приложение завершилось бы до завершения потоков.... таким образом, join
ОСТАНАВЛИВАЕТ ваше приложение от продолжения. Если вы не запустили другой поток ДО того, как вы присоединились, другой поток не может начаться. Мое решение правильное, потому что я join
ПОСЛЕ того, как все темы запущены.
Если вы запускаете поток и сразу же присоединяетесь к нему, вы можете пропустить поток и просто выполнить операцию в обычном вызове функции, многопоточность не требуется, в основном будет тот же эффект.