Использование очереди в многопоточности возвращает адрес функции

#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 or task2 . Вы только что запустили два потока, которые добавляют task1 и task2 себя в очередь, а затем извлекли функции из очереди.

2. это так .. Если я просто печатаю что-то вместо исходной задачи, функция работает, просто при возврате значения она дает мне это

Ответ №1:

target это функция для запуска в потоке. То, что вы заставили поток сделать (и только сделать), — это добавить ссылку на функцию в очередь. Ваша задача не выполняется.

Исправления:

  1. Установите функции задачи для каждой цели.
  2. Поскольку потоки выполняются в одном и том же процессе, доступ к очереди можно получить, не передавая ее в качестве параметра. То же самое и с замком внизу.
  3. Запишите результаты в очередь.
  4. global n не требуется. Это необходимо только в том случае, если вы хотите переназначить n .
  5. Создайте блокировку для управления печатью, если вы будете печатать в потоках. В противном случае это может быть перепутано.
  6. Добавьте соответствующий импорт (почему спрашивающие всегда оставляют импорт ???)

Вы также обнаружите, что это, вероятно, выполняется медленнее, чем простое вычисление простых чисел в одной непараллельной задаче. Процессы 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 информацию о том, как возвращать значения, и использование лямбда-функции было одним из способов, который я получил.