Chinaunix首页 | 论坛 | 博客
  • 博客访问: 123923
  • 博文数量: 83
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 585
  • 用 户 组: 普通用户
  • 注册时间: 2014-05-13 10:26
个人简介

- 毅力与勇气是事业的双飞翼; - 在尝试中成长,在失败中奋起。 - 概览 -> 细读 -> 概览 - 书不在多,在于精。

文章分类

全部博文(83)

文章存档

2016年(2)

2015年(6)

2014年(75)

我的朋友

分类: LINUX

2014-05-29 15:37:20


Python 多线程:创建线程
例子1:

点击(此处)折叠或打开

  1. # coding: utf-8

  2. import threading

  3. class mythread(threading.Thread):  # 通过继承threading.Thread,来创建线程mythread
  4.     def __init__(self, thd_name):
  5.         threading.Thread.__init__(self) # 调用父类的初始化方法。
  6.         self.name = thd_name # self.name 为父类threading.Thread.__init__()中的变量
  7.         #thd_name = self.getName()

  8.     def run_2(self, test_arg):
  9.         self.test_arg = test_arg
  10.         print test_arg

  11.     def run(self): # 重载threading.Thread中的run()方法,实例化线程类mythread后,实际上执行的是run()方法。
  12.         print 'Thread-', self.getName() # 打印线程名,系统默认的线程名格式为Thread-1, Thread-2 ...
  13.       # run_2() #错误调用
  14.         self.run_2('heihei')


  15. thread_list = []
  16. for i in range(10): # 创建10个线程
  17.     t = mythread(str(i) + ' Name is:' + ' hehe')
  18.     thread_list.append(t)

  19. for i in thread_list: # 分别执行这10个线程
  20.     i.start()
  21.     i.join()

例子2:

点击(此处)折叠或打开

  1. #!/usr/bin/python
  2. #coding: utf8
  3. import threading
  4. import time
  5.  
  6. def worker():
  7.     time.sleep(3)
  8.     print "worker"
  9.     time.sleep(2)
  10.     return
  11.  
  12. #下面是使用多线程并发的操作:
  13. for i in xrange(5):
  14.     t = threading.Thread(target=worker)
  15.     t.start()

  16. 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()

点击(此处)折叠或打开

  1. # coding: utf-8

  2. import threading
  3. import time

  4. u'''使用RLock对象来实现简单的线程同步。

  5. '''

  6. class mythread(threading.Thread):
  7.     """docstring for mythread"""
  8.     def __init__(self, thread_name):
  9.         super(mythread, self).__init__() # 调用父类的初始化方法
  10.         self.name = thread_name # name为父类__init__()中的变量。

  11.     def run(self):
  12.         global x
  13.         print self.getName() # 打印线程名

  14.         lock.acquire() # 在acquire()和release()之间的语句可以保证,一次只有一个线程进行操作。

  15.         for i in range(3):
  16.             x = x + 1

  17.         time.sleep(1)
  18.         print x
  19.         lock.release()


  20. lock = threading.RLock()

  21. tl = []
  22. for i in range(10):
  23.     t = mythread('Thread-' + str(i))
  24.     tl.append(t)

  25. x = 0
  26. for i in tl:
  27.     i.start()

#线程同步例子2: Condition()

点击(此处)折叠或打开

  1. # coding: utf-8

  2. import threading
  3. u'''使用Condition对象来控制线程同步。

  4. '''


  5. class Producer(threading.Thread):
  6.     def __init__(self, thd_name):
  7.         threading.Thread.__init__(self)
  8.         self.name = thd_name

  9.     def run(self): # 重载threading.Thread 中的run()方法
  10.         global x

  11.         con.acquire()
  12.         if x == 100000:
  13.             con.wait()
  14.             pass
  15.         else:
  16.             for i in range(100000):
  17.                 x = x + 1
  18.             con.notify()

  19.         print x
  20.         con.release()

  21. class Consumer(threading.Thread):
  22.     """docstring for ClassName"""
  23.     def __init__(self, thd_name):
  24.         super(Consumer, self).__init__() # 另一种继承父类中方法,好处就是万一父类名字变了,子类中调用父类的地方不用跟着改变父类的名称。
  25.         self.name = thd_name # self.name为父类threading.Thread中__init__()方法中的变量

  26.     def run(self):
  27.         global x

  28.         con.acquire()
  29.         if x == 0:
  30.             con.wait()
  31.             pass
  32.         else:
  33.             for i in range(100000):
  34.                 x = x - 1
  35.             con.notify()

  36.         print x
  37.         con.release()


  38. con = threading.Condition()

  39. x = 0

  40. p = Producer('Producer')
  41. c = Consumer('Consumer')

  42. p.start()
  43. c.start()
  44. p.join()
  45. c.join()

  46. print x

  47. # 若删除以上的condition()对象的语句,则每次执行脚本后最终的输出x都可能不一样。

#线程同步3: Queue()

点击(此处)折叠或打开

  1. #coding: utf-8

  2. import threading
  3. import time
  4. import Queue

  5. u'''使用Queue对象来控制多线程的同步问题。典型的例子:生产者、消费者模型。线程需要同步,是因为多个线程对某个共享数据进行修改时,有可能出现意想不到的结果,要保证数据的准确性。

  6. 以下例子,每个生产者Producer线程将数据(线程名)依次存入队列queque_1,而每个消费者Consumer线程则依次从队列queue_1中取出数据(线程名).
  7. 逻辑:
  8. 1.先分别定义:生产者线程和消费者线程。生产者线程的功能是,将线程名放入队列queue_1并且打印相关信息(见run()函数)。而消费者线程的功能是,从队列queue_1中得到数据即生产者Producer的线程名,并打印相关信息。

  9. 2.通过for循环,生成10个生产者线程 和 生成10个消费者线程,并将他们分别放入plist、clist

  10. 3.通过for循环,执行相关的线程。

  11. 总结:
  12. a).就是将要处理的数据按顺序放入队列queue_1,然后按顺序从队列中取出数据,来保证多个线程对共享数据的同步操作。
  13. b).通过继承threading模块中的Thread创建类,重载run()方法后,可以通过start()方法来创建线程!run()是threading.Thread中的自带方法,可通过start来启动线程.
  14. '''

  15. # 1.先分别定义:生产者线程和消费者线程。生产者线程的功能是,将线程名放入队列queue_1并且打印相关信息(见run()函数)。而消费者线程的功能是,从队列queue_1中得到数据即生产者Producer的线程名,并打印相关信息。

  16. class Producer(threading.Thread): # 创建生产者线程类,所需参数见__init__()(因为,在调用类的时候,会首先自动调用__init__()函数。),线程类实际运行的是线程类中自带的run()方法。
  17.     """docstring for ClassName"""
  18.     def __init__(self, threadname):
  19.         #threading.Thread.__init__(self, name = threadname) # 调用父类的初始方法(也可以如下方式); 线程名变量 threadname ; 系统默认的线程名格式为Thread-1, Thread-2 ...
  20.         threading.Thread.__init__(self) # 调用父类的初始方法(必须的,因为Producer类是继承了threading.Thread的);
  21.         self.name = threadname # self.name 为父类threading.Thread.__init__()中的变量

  22.     def run(self): #重写run()方法, 线程类实际运行的是线程类中自带的run()方法,之后就可以通过start()方法来创建线程了。若将run名字改成其它的,如run_2(),则有问题,不执行。
  23.         global queue_1
  24.         queue_1.put(self.getName()) #调用队列put方法,将线程名(threadname = self.getName())添加到队列queue_1中。queue_1 = Queue.Queue()
  25.         print self.getName(), 'put ', self.getName(), ' to queue_1'

  26. class Consumer(threading.Thread):
  27.     """docstring for ClassName"""
  28.     def __init__(self, threadname):
  29.         threading.Thread.__init__(self, name = threadname)

  30.     def run(self):
  31.         global queue_1
  32.         print self.getName(), 'get ', queue_1.get(), ' from queue_1' #调用队列get方法,获取队列queue_1中的内容。

  33. queue_1 = Queue.Queue() #生成队列对象。

  34. # 2.生成10个生产者线程 和 生成10个消费者线程,并将他们分别放入plist、clist
  35. plist = [] #生产者对象列表
  36. clist = [] #消费者对象列表

  37. for i in range(10):
  38.     p = Producer('Producer' + str(i)) # 'Producer' + str(i) 是 Producer 类的线程名 threadname
  39.     #p = Producer() # 尝试: 这样没给参数(实际上是给了一个self参数),会报错,TypeError: __init__() takes exactly 2 arguments (1 given),另一种解决办法可以将Producer类中__init__()注释掉。
  40.     plist.append(p) #生成10个生产者线程的列表,线程名为'Producer' + str(i)

  41. for i in range(10):
  42.     c = Consumer('Consumer' + str(i)) # 'Consumer' + str(i) 是 Consumer 类的线程名 threadname
  43.     clist.append(c) #生成10个消费者线程的列表,线程名为'Consumer' + str(i)

  44. # 3.执行相关的线程。
  45. for i in plist:
  46.     i.start() #执行生产者线程
  47.     i.join() #join()保证了i线程执行完之后才进行下一个任务。

  48. for i in clist:
  49.     i.start() #执行消费者线程
  50.     i.join()




阅读(1061) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~