您的位置:首页 > 编程语言 > Python开发

python 多线程的一点东西

2015-07-09 19:45 716 查看
1,Thread Local类的用法

python 中多线程的并发跟其他语言一样,需要考虑多线程并发访问去全局变量所带来的问题,python的local类解决了这个问题,通过它让每个线程内部有一个相对独立的local保存数据,某一个线程修改了数据,不影响其他线程中保存的数据。

from threading import Thread
import threading
import time
local_value=threading.local()
local_value.x='en'
class threadtest(Thread):

def __init__(self,num):
Thread.__init__(self)
self.num=num

def run(self):
local_value.x=self.getName()
for i in range(self.num):
time.sleep(1)
print(local_value)

threadtest(3).start()
threadtest(2).start()


执行结果是:

Thread-1
Thread-2
Thread-1
Thread-2
Thread-1
[Finished in 3.2s]


这表明,虽然两个线程公用一个local_value.x但是确实相互独立的变量。

另外,

local_value.x=self.getName()放在__init__()中时,运行会报错,说'_thread._local' object has no attribute 'x',目测是因为在初始化__init__的时候,线程还没有建立local_value对象,只有在__init__执行完之后,才可以开始赋值(不过对于这一点我不确定,看源码也看晕了)。

2,Thread join()方法的用法及含义:

join()源码中的解释:

"""Wait until the thread terminates.

This blocks the calling thread until the thread whose join() method is
called terminates -- either normally or through an unhandled exception
or until the optional timeout occurs.

When the timeout argument is present and not None, it should be a
floating point number specifying a timeout for the operation in seconds
(or fractions thereof). As join() always returns None, you must call
isAlive() after join() to decide whether a timeout happened -- if the
thread is still alive, the join() call timed out.

When the timeout argument is not present or None, the operation will
block until the thread terminates.

A thread can be join()ed many times.

join() raises a RuntimeError if an attempt is made to join the current
thread as that would cause a deadlock. It is also an error to join() a
thread before it has been started and attempts to do so raises the same
exception.

"""


当某个子线程调用join()时,主线程将阻塞,直至该线程执行完毕,

当每个子线程调用都join(),且不设置参数时

from threading import Thread
import threading
import time
local_value=threading.local()
class threadtest(Thread):

def __init__(self,num):
Thread.__init__(self)
self.num=num
#local_value.x=self.getName()
def run(self):
local_value.x=self.getName()
for i in range(self.num):
time.sleep(1)
print(local_value.x)
from threading import current_thread

#print(current_thread(),local_value.__dict__,'--')
a=threadtest(2)
b=threadtest(2)
c=threadtest(2)
a.start()
a.join()
b.start()
b.join()
c.start()
c.join()
for i in range(2):
time.sleep(1)
print(current_thread())


结果是:

Thread-1
Thread-1
Thread-2
Thread-2
Thread-3
Thread-3
<_MainThread(MainThread, started 6688)>
<_MainThread(MainThread, started 6688)>
[Finished in 8.2s]


即:哪个子线程先调用join,就先完成它的任务,依次执行,不仅是主线程,其他的子线程也必须为调用了join的线程让路,让它执行完毕,在执行下一个调用了join的子线程,最后才轮到主线程上台(主线程:卧槽,我才是老大啊!)

如果每个子线程都设置时间参数,但是时间参数小于完成任务所需的时间的话

from threading import Thread
import threading
import time
local_value=threading.local()
class threadtest(Thread):

def __init__(self,num):
Thread.__init__(self)
self.num=num
#local_value.x=self.getName()
def run(self):
local_value.x=self.getName()
for i in range(self.num):
time.sleep(1)
print(local_value.x)
from threading import current_thread

#print(current_thread(),local_value.__dict__,'--')
a=threadtest(6)
b=threadtest(6)
#c=threadtest(6)
a.start()
b.start()
a.join(2)
b.join(2)
#c.start()
#c.join(2)
#以下是主线程
for i in range(2):
#ime.sleep(1)
print(current_thread())


结果为:

Thread-1
Thread-2
Thread-1
Thread-2
Thread-1
Thread-2
Thread-1
Thread-2
<_MainThread(MainThread, started 8652)>
<_MainThread(MainThread, started 8652)>
Thread-1
Thread-2
Thread-1
Thread-2
[Finished in 6.2s]

从结果可以看出,子线程开始确实阻塞了主线程,但是没有阻塞其他子线程,所以两个子线程仍然是并行执行,一共阻塞了4秒钟(线程1,和线程2一起),四秒钟后程序开始执行join之后的代码,也就是主线程的代码,从这之后,主线程和子线程之间是并行关系。

总结一下(不要告诉我你只看总结)

1,子线程只要调用了join函数,就会阻塞主线程,不管有没有设置参数,

2,子线程如果调用join函数,设置了时间参数,主线程在设置的时间内被阻塞,子线之间一直是并行的,时间到了后,程序将会执行join()之后的代码。

3,如果子线程调用join函数,没有设置时间参数,那么子线程之间不会并行,而是有优先成那个调用了join的子线程。

如果不调用join,那么主线程不会为子线程阻塞,所有线程并发执行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: