简体   繁体   中英

same program different output in threading module

start.py code is as below.

import threading
class myThread(threading.Thread):
        def __init__(self, threadID, name):
                threading.Thread.__init__(self)
                self.threadID = threadID
                self.name = name

        def run(self):
                currentThreadname = threading.currentThread()
                print "running in ", currentThreadname

thread = myThread(1,"mythrd")
thread.start()

Start it with python for two times.

python start.py
running in  <myThread(mythrd, started 140461133485824)>
python start.py
running in  <myThread(mythrd, started 140122860668672)>

run.py code is as below.

import threading
class myThread(threading.Thread):
        def __init__(self, threadID, name):
                threading.Thread.__init__(self)
                self.threadID = threadID
                self.name = name

        def run(self):
                currentThreadname = threading.currentThread()
                print "running in ", currentThreadname

thread = myThread(1,"mythrd")
thread.run()

run.py is only one line different from start.py.
Now start run.py for two times.

python  run.py
running in  <_MainThread(MainThread, started 139854546364160)>
python  run.py
running in  <_MainThread(MainThread, started 139854546364160)>

startandrun.py code is as below.

class myThread(threading.Thread):
    def __init__(self, threadID, name):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name

    def run(self):
        currentThreadname = threading.currentThread()
        print "running in ", currentThreadname

thread = myThread(1,"mythrd")
thread.start()
thread.run()

Now start startandrun.py for two times also.

python  startandrun.py
running in  <myThread(mythrd, started 140317119899392)>
running in  <_MainThread(MainThread, started 140317144454912)>
python  startandrun.py
running in running in  <_MainThread(MainThread, started 139980210505472)>
 <myThread(mythrd, started 139980185949952)>

As JohanL say:
When running two separate threads, all bets are off as to which will execute first.
You are basically leaving the scheduling to the operating system. The first time to execute startandrun.py, thread.start() was executed before thread.run() ,it result in the output:

running in  <myThread(mythrd, started 140317119899392)>
running in  <_MainThread(MainThread, started 140317144454912)>

The second time to execute startandrun.py, thread.start() was executed after thread.run() ,why not result in the output:

running in  <_MainThread(MainThread, started 140317144454912)>
running in  <myThread(mythrd, started 140317119899392)>

instead of

running in running in  <_MainThread(MainThread, started 139980210505472)>
 <myThread(mythrd, started 139980185949952)>

This is happening because of the way you are printing the values:

print "running in ", currentThreadname

Adding a comma is similar to:

print 'running in ' # without new line at the end
print currentThreadname

And since the two functions are running at the same time here is how the order is executed:

print 'running in ' # without new line FUNCTION #1
print 'running in ' # without new line FUNCTION #2
print currentThreadName # with new line at the end FUNCTION #1
print currentThreadName # with new line at the end FUNCTION #2

Try using one print statement without commas to understand how it should be:

def run(self):
    currentThreadname = threading.currentThread()
    print "running in {}".format(currentThreadname)

This will behave normally but since the two functions are printing at the same time, you might get the following output:

running in <myThread(mythrd, started 10716)>running in <_MainThread(MainThread, started 12132)>

So to prove that this will work you can use a delay in between the two calls using time.sleep() :

import threading
import time

class myThread(threading.Thread):
    def __init__(self, threadID, name):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name

    def run(self):
        currentThreadname = threading.currentThread()
        print "running in {}".format(currentThreadname)

thread = myThread(1,"mythrd")
thread.start()
time.sleep(0.1)
thread.run()

Now you can see that you get your desired output because each function is printing one time with a 0.1 sec delay in between the calls:

running in <myThread(mythrd, started 5600)>
running in <_MainThread(MainThread, started 7716)>

EDIT:

Your issue is exactly why you should use multithreading instead of running the same thread twice. When you use multithreading You can use thread.join() which will wait for the thread to finish off and then continue the code, or you can use threading.lock() so you can continue your code but lock a function to be used by one thread at a time. Here are some examples:

thread.join() :

thread = myThread(1, "mythrd")
thread2 = myThread(2, "thrd2")
thread.start()
thread.join() # code will stop here and wait for thread to finish then continue
thread2.run()

threading.lock() :

....
    def run(self):
        with lock: # if one thread uses this lock the other threads have to wait
            currentThreadname = threading.currentThread()
            print "running in ", currentThreadname

thread = myThread(1, "mythrd")
thread2 = myThread(2, "thrd2")
lock = threading.Lock()
thread.start() 
thread2.run()
# code keeps running even if there are threads waiting for the lock

So, all you want is to synchronize your threads. It can be done easily using the join() function in threading library.

You can do something like this

class myThread(threading.Thread):
    def __init__(self, threadID, name):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name

    def run(self):
        currentThreadname = threading.currentThread()
        print "running in ", currentThreadname

thread = myThread(1,"mythrd")
t1 =  thread.start()
t1.join()
t2 =  thread.run()
t2.join()

You can also use semaphore and Lock for better reasons. See the docs for more detail.

Probably you do not understand how threads are working. Read this carefully.

I highly suggest you to use ThreadPoolExecutor from the futures library.

What version python were you using? In python 2, "print" is not thread safe. Please see http://tech.queryhome.com/54593/is-print-thread-safe-in-python-2-6-2-7 .

If threads switch during "print", the outputs are mixed, like what you saw.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM