В чем разница между двумя разделами кода (о Python GIL)? - PullRequest
0 голосов
/ 02 июля 2018

Код фрагмента 1 :

before = time()
urls = ['https://google.com'] * 5
for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    thread1.join()
after = time()
print(after - before)

Для запуска кода, результат 5.740652799606323
График потоков - это: ссылка на изображение

Код фрагмента 2 :

before = time()
thread1 = Thread(target=get_content, args=('https://google.com',))
thread2 = Thread(target=get_content, args=('https://google.com',))
thread3 = Thread(target=get_content, args=('https://google.com',))
thread4 = Thread(target=get_content, args=('https://google.com',))
thread5 = Thread(target=get_content, args=('https://google.com',))
thread1.start()
thread2.start()
thread3.start()
thread4.start()
thread5.start()
thread1.join()
thread2.join()
thread3.join()
thread4.join()
thread5.join()
after = time()
print(after - before)

Чтобы запустить код, результат будет: 1.102950096130371
График потоков - это: ссылка на изображение

Я думаю, что результат будет похожим. Но окончательного результата нет. Почему?
Кто-нибудь может мне помочь объяснить это?

Ответы [ 3 ]

0 голосов
/ 02 июля 2018

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

for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    thread1.join()

То, что вы, вероятно, захотите сделать при работе с потоками, - это сохранить каждый поток в контейнере (списке), запустить все потоки и дождаться завершения всех из них.

ths = []
for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    ths.append(thread1)

for t in ths:
    t.join()

Этот код фактически делает то, что делает второй фрагмент , просто с помощью цикла.

0 голосов
/ 02 июля 2018

thread1.join() ожидает окончания потока. У вас есть это в цикле, так что это означает, что цикл не перейдет к следующей итерации, пока 1-й запрос не будет завершен.

По сути, вы "убили" идею многопоточности и заставили программу выполнять запросы по одному.

Один из способов изменить это сделать что-то вроде этого:

before = time()
urls = ['https://google.com'] * 5
threads = []
for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    threads.append(thread1)
[t.join() for t in threads]
after = time()
print(after - before)
0 голосов
/ 02 июля 2018
for url in urls:
    thread1 = Thread(target=get_content, args=(url,))
    thread1.start()
    thread1.join()

Ваш .join находится внутри цикла for, поэтому он начнет и присоединится первым, а затем перейдет к следующему потоку. После этого у вас должен быть второй цикл, чтобы присоединиться к ним.

...