Python 多线程:创建线程
例子1:
-
# coding: utf-8
-
-
import threading
-
-
class mythread(threading.Thread): # 通过继承threading.Thread,来创建线程mythread。
-
def __init__(self, thd_name):
-
threading.Thread.__init__(self) # 调用父类的初始化方法。
-
self.name = thd_name # self.name 为父类threading.Thread.__init__()中的变量
-
#thd_name = self.getName()
-
-
def run_2(self, test_arg):
-
self.test_arg = test_arg
-
print test_arg
-
-
def run(self): # 重载threading.Thread中的run()方法,实例化线程类mythread后,实际上执行的是run()方法。
-
print 'Thread-', self.getName() # 打印线程名,系统默认的线程名格式为Thread-1, Thread-2 ...
-
# run_2() #错误调用
-
self.run_2('heihei')
-
-
-
thread_list = []
-
for i in range(10): # 创建10个线程
-
t = mythread(str(i) + ' Name is:' + ' hehe')
-
thread_list.append(t)
-
-
for i in thread_list: # 分别执行这10个线程
-
i.start()
-
i.join()
例子2:
-
#!/usr/bin/python
-
#coding: utf8
-
import threading
-
import time
-
-
def worker():
-
time.sleep(3)
-
print "worker"
-
time.sleep(2)
-
return
-
-
#下面是使用多线程并发的操作:
-
for i in xrange(5):
-
t = threading.Thread(target=worker)
-
t.start()
-
-
print "current has %d threads" % (threading.activeCount() - 1)
接下来讲讲线程的同步,
线程需要同步的原因是,如果有多个线程同时对某个共享数据进行修改,则有可能得到预想不到的结果,故需要保证线程间操作的同步。
线程同步主要方法有3中:
1.使用Thread对象中的Lock和RLock可以实现简单的线程同步,主要有请求锁acquire()和释放锁release()。对于需要每次只有一个线程操作的共享数据,可以将操作过程放在acquire()和release()之间。
lock_1 = threading.RLock(); lock_1.acquire() .... lock_1.release()
2.使用条件变量保存线程同步, Condition对象。 主要方法有acquire(), release(),wait(),notify(),notifyAll()
con_1 = threading.Condition()
3.使用队列Queue对象来保持线程同步.(最常用)
,原理是,将共享数据放入队列中。
queue_1 = Queue.Queue()
#线程同步例子1:Rlock()
-
# coding: utf-8
-
-
import threading
-
import time
-
-
u'''使用RLock对象来实现简单的线程同步。
-
-
'''
-
-
class mythread(threading.Thread):
-
"""docstring for mythread"""
-
def __init__(self, thread_name):
-
super(mythread, self).__init__() # 调用父类的初始化方法
-
self.name = thread_name # name为父类__init__()中的变量。
-
-
def run(self):
-
global x
-
print self.getName() # 打印线程名
-
-
lock.acquire() # 在acquire()和release()之间的语句可以保证,一次只有一个线程进行操作。
-
-
for i in range(3):
-
x = x + 1
-
-
time.sleep(1)
-
print x
-
lock.release()
-
-
-
lock = threading.RLock()
-
-
tl = []
-
for i in range(10):
-
t = mythread('Thread-' + str(i))
-
tl.append(t)
-
-
x = 0
-
for i in tl:
-
i.start()
#线程同步例子2: Condition()
-
# coding: utf-8
-
-
import threading
-
u'''使用Condition对象来控制线程同步。
-
-
'''
-
-
-
class Producer(threading.Thread):
-
def __init__(self, thd_name):
-
threading.Thread.__init__(self)
-
self.name = thd_name
-
-
def run(self): # 重载threading.Thread 中的run()方法
-
global x
-
-
con.acquire()
-
if x == 100000:
-
con.wait()
-
pass
-
else:
-
for i in range(100000):
-
x = x + 1
-
con.notify()
-
-
print x
-
con.release()
-
-
class Consumer(threading.Thread):
-
"""docstring for ClassName"""
-
def __init__(self, thd_name):
-
super(Consumer, self).__init__() # 另一种继承父类中方法,好处就是万一父类名字变了,子类中调用父类的地方不用跟着改变父类的名称。
-
self.name = thd_name # self.name为父类threading.Thread中__init__()方法中的变量
-
-
def run(self):
-
global x
-
-
con.acquire()
-
if x == 0:
-
con.wait()
-
pass
-
else:
-
for i in range(100000):
-
x = x - 1
-
con.notify()
-
-
print x
-
con.release()
-
-
-
con = threading.Condition()
-
-
x = 0
-
-
p = Producer('Producer')
-
c = Consumer('Consumer')
-
-
p.start()
-
c.start()
-
p.join()
-
c.join()
-
-
print x
-
-
# 若删除以上的condition()对象的语句,则每次执行脚本后最终的输出x都可能不一样。
#线程同步3: Queue()
-
#coding: utf-8
-
-
import threading
-
import time
-
import Queue
-
-
u'''使用Queue对象来控制多线程的同步问题。典型的例子:生产者、消费者模型。线程需要同步,是因为多个线程对某个共享数据进行修改时,有可能出现意想不到的结果,要保证数据的准确性。
-
-
以下例子,每个生产者Producer线程将数据(线程名)依次存入队列queque_1,而每个消费者Consumer线程则依次从队列queue_1中取出数据(线程名).
-
逻辑:
-
1.先分别定义:生产者线程和消费者线程。生产者线程的功能是,将线程名放入队列queue_1并且打印相关信息(见run()函数)。而消费者线程的功能是,从队列queue_1中得到数据即生产者Producer的线程名,并打印相关信息。
-
-
2.通过for循环,生成10个生产者线程 和 生成10个消费者线程,并将他们分别放入plist、clist
-
-
3.通过for循环,执行相关的线程。
-
-
总结:
-
a).就是将要处理的数据按顺序放入队列queue_1,然后按顺序从队列中取出数据,来保证多个线程对共享数据的同步操作。
-
b).通过继承threading模块中的Thread创建类,重载run()方法后,可以通过start()方法来创建线程!run()是threading.Thread中的自带方法,可通过start来启动线程.
-
'''
-
-
# 1.先分别定义:生产者线程和消费者线程。生产者线程的功能是,将线程名放入队列queue_1并且打印相关信息(见run()函数)。而消费者线程的功能是,从队列queue_1中得到数据即生产者Producer的线程名,并打印相关信息。
-
-
class Producer(threading.Thread): # 创建生产者线程类,所需参数见__init__()(因为,在调用类的时候,会首先自动调用__init__()函数。),线程类实际运行的是线程类中自带的run()方法。
-
"""docstring for ClassName"""
-
def __init__(self, threadname):
-
#threading.Thread.__init__(self, name = threadname) # 调用父类的初始方法(也可以如下方式); 线程名变量 threadname ; 系统默认的线程名格式为Thread-1, Thread-2 ...
-
threading.Thread.__init__(self) # 调用父类的初始方法(必须的,因为Producer类是继承了threading.Thread的);
-
self.name = threadname # self.name 为父类threading.Thread.__init__()中的变量
-
-
def run(self): #重写run()方法, 线程类实际运行的是线程类中自带的run()方法,之后就可以通过start()方法来创建线程了。若将run名字改成其它的,如run_2(),则有问题,不执行。
-
global queue_1
-
queue_1.put(self.getName()) #调用队列put方法,将线程名(threadname = self.getName())添加到队列queue_1中。queue_1 = Queue.Queue()
-
print self.getName(), 'put ', self.getName(), ' to queue_1'
-
-
class Consumer(threading.Thread):
-
"""docstring for ClassName"""
-
def __init__(self, threadname):
-
threading.Thread.__init__(self, name = threadname)
-
-
def run(self):
-
global queue_1
-
print self.getName(), 'get ', queue_1.get(), ' from queue_1' #调用队列get方法,获取队列queue_1中的内容。
-
-
queue_1 = Queue.Queue() #生成队列对象。
-
-
# 2.生成10个生产者线程 和 生成10个消费者线程,并将他们分别放入plist、clist
-
plist = [] #生产者对象列表
-
clist = [] #消费者对象列表
-
-
for i in range(10):
-
p = Producer('Producer' + str(i)) # 'Producer' + str(i) 是 Producer 类的线程名 threadname
-
#p = Producer() # 尝试: 这样没给参数(实际上是给了一个self参数),会报错,TypeError: __init__() takes exactly 2 arguments (1 given),另一种解决办法可以将Producer类中__init__()注释掉。
-
plist.append(p) #生成10个生产者线程的列表,线程名为'Producer' + str(i)
-
-
for i in range(10):
-
c = Consumer('Consumer' + str(i)) # 'Consumer' + str(i) 是 Consumer 类的线程名 threadname
-
clist.append(c) #生成10个消费者线程的列表,线程名为'Consumer' + str(i)
-
-
# 3.执行相关的线程。
-
for i in plist:
-
i.start() #执行生产者线程
-
i.join() #join()保证了i线程执行完之后才进行下一个任务。
-
-
for i in clist:
-
i.start() #执行消费者线程
-
i.join()
阅读(1135) | 评论(0) | 转发(0) |