2

I want to use threading package to calculate the square of num and my code like,

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")

However, I am confused about where should I put the join() method.Although, they both get same answer, I guess there are some differeces between them.

4daJKong
  • 1,825
  • 9
  • 21
  • If you start a thread an immediately join it you can skip the thread and just perform the operation in a normal function call, no multithreading needed, will have basically the exact same effect. – luk2302 Nov 18 '22 at 08:30
  • Does this answer your question? [What is the use of join() in Python threading?](https://stackoverflow.com/questions/15085348/what-is-the-use-of-join-in-python-threading) – luk2302 Nov 18 '22 at 08:31
  • @luk2302 thanks for your reply, I am still confused about this method after reading website, did it means it is meaningless of join method, join is only to make the code clear? – 4daJKong Nov 18 '22 at 08:55

3 Answers3

3

If you immediately join after started an thread, it means that wait until it executes. However, this isn't different than calling function normally inside main thread. Assume that functions works takes a bit of time and you need to process them at the same time. Then you can start them and uncomment joins. This is your current code snippet workflow

->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.

However if you change comments of joins this is new workflow

->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
...

So here even when you are waiting to finish X, your other threads like y and z still processing whatever you are doing inside.

EDIT: You should remove the joins where right after the start and uncomment threads that are been in the end. That would be a more appropriate. Also, as processors are fast enough to complete simple math just in a millisecond, you will not experience any difference.

Where u should use the joins is completely dependent on your program. For your situation using at the end probably would be the best.

However, assume you will have another thread called X_2 that will use result of thread X_1. Then before creating thread X_2, you should join thread X_1.

  • thanks again, did you mean it is not necessary to add `join` in anywhere? sorry, I am still confused, if `my_squr` takes long time to run, which one is correct? – 4daJKong Nov 18 '22 at 08:53
  • In your situation, using at the end would be correct – Mustafa KÜÇÜKDEMİRCİ Nov 18 '22 at 08:58
  • @4daJKong, Re, "...not necessary to add join anywhere?" `t.join()` is how one thread can wait for another thread to end. If thread `t` does some thing, and \*IF\* there's some point in some other thread `u` beyond which `u` should not proceed until `t` has done its thing, then thread `u` can call `t.join()` at that point, and the join call will not return until thread `t` has done its thing. – Solomon Slow Nov 18 '22 at 14:29
  • @4daJKong, In your example, the last thing your main thread does is, `print("done")`. If you don't want that to happen until after the other three threads are done, then you can ensure that by having the main thread `join()` all of those other threads before it prints the "done" message. – Solomon Slow Nov 18 '22 at 14:29
1

You could construct a list of the threads then join them all once your loop terminates:

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")
DarkKnight
  • 19,739
  • 3
  • 6
  • 22
  • thanks for your reply, the main problem is I don't know where should I add `join`, in loop or out loop, because they both return same reuslt, but I want to use mulitthreading – 4daJKong Nov 18 '22 at 09:08
  • The join in my answer is outside the loop - i.e., it's a clean-up operation. I'm interested to know what your long-running function will be doing. I hope it's not going to be CPU intensive because, if it is, multithreading will not be a good option – DarkKnight Nov 18 '22 at 09:11
1

Join simply stops the application from ending before the thread completes.
So you want to join threads AFTER they have started.

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")
eatmeimadanish
  • 3,809
  • 1
  • 14
  • 20
  • thanks for your reply, the main problem is I don't know where should I add `join`, in loop or out loop, because they both return same reuslt, but I want to use mulitthreading – 4daJKong Nov 18 '22 at 09:08
  • Re, "join...stops the application." That's a misleading assertion. `t.join()` _waits_ for thread `t` to end. If you happen to call `t.join()` from some thread that you think of as "the application," then sure, join stops the application. But _any_ thread can join any other thread. The simplest explanation for what join does is the one that explains how it behaves in _any_ situation. `t.join()` _does nothing._ It continues to do nothing until thread `t` ends, and then it returns. – Solomon Slow Nov 18 '22 at 14:22
  • Without `join` your application would end before the threads completed.... thus `join` STOPS your application from continuing. If you haven't launched another thread BEFORE you join then the other thread can't start. My solution is correct because I `join` AFTER all the threads are started. – eatmeimadanish Nov 22 '22 at 03:38