#python #python-3.x #multithreading #queue #python-multiprocessing
#питон #python-3.x #многопоточность #очередь #python -многопроцессорная обработка
Вопрос:
Я пытаюсь реализовать многопоточную программу, которая находит простые числа по нескольким потокам и агрегирует их результат.
Я использую очередь для фактического хранения возвращаемых значений. но когда я печатаю значения queue печатается только адрес функции
n = int(input("Enter the value:"))
def task1():
global n
print("Task 1 assigned to thread: {}".format(threading.current_thread().name))
print("ID of process running task 1: {}".format(os.getpid()))
a=[]
for i in range(2,n//2):
c=0
for j in range(2,i 1):
if(i%j==0):
c =1
if(c<=1):
a.append(i)
return a
def task2():
global n
print("Task 2 assigned to thread: {}".format(threading.current_thread().name))
print("ID of process running task 2: {}".format(os.getpid()))
a=[]
for i in range(n//2 1,n):
c=0
for j in range(2,i 1):
if(i%j==0):
c =1
if(c<=1):
a.append(i)
return a
import queue
que=queue.Queue()
t1 = threading.Thread(target=lambda q: q.put(task1), args=(que,), name='t1')
t2 = threading.Thread(target=lambda q: q.put(task2), args=(que,), name='t2')
# starting threads Spawn
t1.start()
t2.start()
# wait until all threads finish Sync
t1.join()
t2.join()
while not que.empty():
result=que.get()
print(result)
после запуска кода это значение, которое я получаю
<function task1 at 0x00000204A9A11438>
<function task2 at 0x00000204A9A11288>
Мне нужно вывести массив простых чисел вместо адреса.
Комментарии:
1. «Я использую очередь для фактического хранения возвращаемых значений». — э, нет? Ни одна часть этого кода не сохраняет возвращаемые значения в очереди. Ни одна часть этого кода даже не запускает
task1
ortask2
. Вы только что запустили два потока, которые добавляютtask1
иtask2
себя в очередь, а затем извлекли функции из очереди.2. это так .. Если я просто печатаю что-то вместо исходной задачи, функция работает, просто при возврате значения она дает мне это
Ответ №1:
target
это функция для запуска в потоке. То, что вы заставили поток сделать (и только сделать), — это добавить ссылку на функцию в очередь. Ваша задача не выполняется.
Исправления:
- Установите функции задачи для каждой цели.
- Поскольку потоки выполняются в одном и том же процессе, доступ к очереди можно получить, не передавая ее в качестве параметра. То же самое и с замком внизу.
- Запишите результаты в очередь.
global n
не требуется. Это необходимо только в том случае, если вы хотите переназначитьn
.- Создайте блокировку для управления печатью, если вы будете печатать в потоках. В противном случае это может быть перепутано.
- Добавьте соответствующий импорт (почему спрашивающие всегда оставляют импорт ???)
Вы также обнаружите, что это, вероятно, выполняется медленнее, чем простое вычисление простых чисел в одной непараллельной задаче. Процессы Python ограничены глобальной блокировкой интерпретатора (GIL) для одновременного выполнения кода Python только в одном потоке, поэтому потоки сериализуются, если они выполняют работу, связанную с процессором, что и есть.
Потоки идеально подходят для распараллеливания операций ввода-вывода. Используйте процессы через multiprocessing
модуль для выполнения задач, связанных с ЦП, но учтите, что накладные расходы на создание процессов и межпроцессное взаимодействие для отправки параметров и результатов обратно в основной процесс могут перегружать простые операции, связанные с ЦП, подобные этой, если они не выполняются в течение значительного периода времени.
import threading
import os
import queue
n = int(input("Enter the value:"))
lock = threading.Lock()
que = queue.Queue()
def task1():
with lock:
print("Task 1 assigned to thread: {}".format(threading.current_thread().name))
print("ID of process running task 1: {}".format(os.getpid()))
a=[]
for i in range(2,n//2):
c=0
for j in range(2,i 1):
if(i%j==0):
c =1
if(c<=1):
a.append(i)
que.put(a)
def task2():
with lock:
print("Task 2 assigned to thread: {}".format(threading.current_thread().name))
print("ID of process running task 2: {}".format(os.getpid()))
a=[]
for i in range(n//2 1,n):
c=0
for j in range(2,i 1):
if(i%j==0):
c =1
if(c<=1):
a.append(i)
que.put(a)
t1 = threading.Thread(target=task1, name='t1')
t2 = threading.Thread(target=task2, name='t2')
# starting threads Spawn
t1.start()
t2.start()
# wait until all threads finish Sync
t1.join()
t2.join()
while not que.empty():
result=que.get()
print(result)
Вывод:
Enter the value: 100
Task 1 assigned to thread: t1
ID of process running task 1: 3864
Task 2 assigned to thread: t2
ID of process running task 2: 3864
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]
[53, 59, 61, 67, 71, 73, 79, 83, 89, 97]
Ответ №2:
Вы помещаете task1
и taks2
(которые являются обеими функциями) в очередь:
.put(task1)
t1 = threading.Thread(target=lambda q: q.put(task1), args=(que,), name='t1')
поэтому, когда вы перечитываете его содержимое, вы также получаете функции.
Кроме того, несмотря на то, что вы, похоже, намереваетесь передать queue que
в качестве аргумента, функции task1
и taks2
не имеют параметров. Я также не понимаю использования лямбда-выражения в конструкторах потоков, но это уже другой вопрос.
Поскольку это похоже на домашнее задание, я лишь кратко отвечаю на ваш вопрос и не привожу полный рабочий пример.
Комментарии:
1. Я искал в stackoverflow информацию о том, как возвращать значения, и использование лямбда-функции было одним из способов, который я получил.