What is the best way to use threading in this example?

Asked

Viewed 113 times

5

That is the challenge:

Create a function that shows an item from a list every second. Using threads, make the program show all items as quickly as possible

My code:

import threading
import time

threads = int(input('Quantas threads você deseja? '))
lista = list(range(0, 50000))


if threads > len(lista):
    threads = len(lista)

passo = len(lista) // threads
n = 0
n2 = passo

def thread(n, n2):
    for i in lista[n:n2]:
        print(i)
        time.sleep(1)


for i in range(threads - 1):
    threading.Thread(target=thread, args=(n, n2)).start()
    n = n2
    n2 += passo
threading.Thread(target=thread, args=(n, len(lista))).start()

It works, but the prints are not in order, there is some way to get them in order with the same efficiency or even more?

I also noticed that the work of each thread is different (the last thread usually has more items), so some end very quickly, and others very slowly. Is there any way to leave a number of threads "fixed" until the program lists all items?

1 answer

1

One solution is to pass each thread a continuous part of the list, such as [..., n, n+1, n+2, ...] and make each Thread assemble a text to be printed. Then each Thread prints its own text.

num_threads = int(input('Quantas threads você deseja? '))
lista = list(range(0, 20000))

lock = threading.Lock()

# Cada Thread imprime uma parte contínua da lista
def imprime_lista(*lista):
    texto = '\n'.join(map(str, lista))
    with lock:
        print(texto)

total_valores = len(lista)
lista_threads = []

# Passa uma parte da lista para a cada Thread
for i in range(num_threads):
    lim_inf = int((i)*(total_valores/num_threads)) # Limite inferior para divisão da lista
    lim_sup = int((i+1)*(total_valores/num_threads)) # Limite superior para divisão da lista
    lista_threads.append(threading.Thread(target=imprime_lista, args=(lista[lim_inf:lim_sup])))

for t in lista_threads:
    t.start()

With the Lock() It is possible to block a Thread from accessing part of the code. Since all Threads perform the same function, they all form the text to be printed in parallel, but are locked before printing the text.

With the command with lock:, I guarantee that each Thread will print your text and then release it for another Thread to do the same. So the impressions do not stand out.

In the tests I did, perhaps because they all performed the same function, the order in which the Threads printed their respective texts (i.e., accessed the blocked part) followed the order in which they were initialized by t.start().

  • could explain to me the use of threading.lock()?

  • I edited adding a brief explanation with what I know. I’m sorry if it’s not enough for your problem, but my knowledge of Threads with Lock doesn’t go much further than that.

  • like this method of adding threads in a list, I will definitely use

  • Like the total_valores and the num_threads are fixed, would put their calculation total_valores/num_threads out of the loop to avoid redoing it.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.