threading简介
线程是操作系统能够进行运算调度的最小单位。线程被包含在进程中,是进程中实际处理单位。一条线程就是一堆指令集合。一条线程是指进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.进程(process)是一块包含了某些资源的内存区域
Thread类
Thread是线程类,有两种使用方法,直接传入要运行的方法或从Thread继承并覆盖run():1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28# coding:utf-8
import threading
import time
#方法一:将要执行的方法作为参数传给Thread的构造方法
def action(arg):
    time.sleep(1)
    print 'the arg is:%s\r' %arg
for i in xrange(4):
    t =threading.Thread(target=action,args=(i,))
    t.start()
print 'main thread end!'
#方法二:从Thread继承,并重写run()
class MyThread(threading.Thread):
    def __init__(self,arg):
        super(MyThread, self).__init__()#注意:一定要显式的调用父类的初始化函数。
        self.arg=arg
    def run(self):#定义每个线程要运行的函数
        time.sleep(1)
        print 'the arg is:%s\r' % self.arg
for i in xrange(4):
    t =MyThread(i) # 直接可运行run函数
    t.start()
print 'main thread end!'
总结概括
| 名称 | 类型 | 描述 | 
|---|---|---|
| Thread | 类 | |
| Lock | 类 | |
| Rlock | 类 | |
| Condition | 类 | |
| [Bounded]Semaphore | 类 | |
| Event | 类 | |
| Timer | 类 | |
| local | 类 | |
| threading.currentThread() | 常用方法 | 返回当前的线程变量 | 
| threading.enumerate() | 常用方法 | 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程 | 
| threading.activeCount() | 常用方法 | 返回正在运行的线程数量 | 
| threading.TIMEOUT_MAX | 常量 | 设置threading全局超时时间 | 
构造方法
| 1 | Thread(group=None, target=None, name=None, args=(), kwargs={}) | 
实例方法
| 1 | isAlive(): 返回线程是否在运行。正在运行指启动后、终止前。 | 
阻塞
与主程序并行
| 1 | # coding:utf-8 | 
阻塞主程序
使多线程编程顺序执行,失去了多线程的意义,不建议使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# coding:utf-8
import threading
import time
def action(arg):
    time.sleep(1)
    print  '子程序启动!the thread name is:%s\r' % threading.currentThread().getName()
    print 'the arg is:%s\r' %arg
    time.sleep(1)
if __name__ == '__main__':
    
    for i in xrange(4):
        t =threading.Thread(target=action,args=(i,))
        t.start()
        t.join()
    print '主程序完成!'
阻塞子程序
所有子程序并发完成,然后再执行主程序(常用此方法)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16# coding:utf-8
import threading
import time
def action(arg):
    time.sleep(1)
    print  '子程序启动!the thread name is:%s\r' % threading.currentThread().getName()
    print 'the arg is:%s\r' %arg
    time.sleep(1)
if __name__ == '__main__':
    
    for i in xrange(4):
        t =threading.Thread(target=action,args=(i,))
        t.start()
    t.join()
    print '主程序完成!'
主完子完
只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以用setDaemon方法
| 1 | # coding:utf-8 | 
join和setDaemon一起使用1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#coding:utf-8
import threading
import time
def action(arg):
    time.sleep(1)
    print  'sub thread start!the thread name is:%s    ' % threading.currentThread().getName()
    print 'the arg is:%s   ' %arg
    time.sleep(1)
thread_list = []    #线程存放列表
for i in xrange(4):
    t =threading.Thread(target=action,args=(i,))
    t.setDaemon(True)
    thread_list.append(t)
for t in thread_list:
    t.start()
for t in thread_list:
    t.join()
验证了 join()阻塞当前上下文环境的线程,直到调用此方法的线程终止或到达指定的timeout,即使设置了setDeamon(True)主线程依然要等待子线程结束。
Lock、Rlock类
| 1 | """ | 
简言之:Lock属于全局,Rlock属于线程。
构造方法: Lock(),Rlock(),推荐使用Rlock()
实例方法:
  acquire([timeout]): 尝试获得锁定。使线程进入同步阻塞状态。
  release(): 释放锁。使用前线程必须已获得锁定,否则将抛出异常。
例子一(未使用锁):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24import time
import threading
def addNum():
    global num #在每个线程中都获取这个全局变量
    # num-=
    temp=num
    print('--get num:',num )
    #time.sleep(0.1)
    num =temp-#对此公共变量进行-1操作
num = 1#设定一个共享变量
thread_list = []
    for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)
for t in thread_list: #等待所有线程执行完毕
    t.join()
print('final num:', num )
例子二(使用锁):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27import time
import threading
def addNum():
    global num #在每个线程中都获取这个全局变量
    # num-=
    lock.acquire()    #加同步锁
    temp=num
    print('--get num:',num )
    #time.sleep(0.1)
    num =temp-#对此公共变量进行-1操作
    lock.release()    #解锁
num = 1#设定一个共享变量
thread_list = []
lock=threading.Lock()  #创建lock对象
for i in range(100):
    t = threading.Thread(target=addNum)
    t.start()
    thread_list.append(t)
for t in thread_list: #等待所有线程执行完毕
    t.join()      #所有线程执行完后主程序才能结束
print('final num:', num )
可以看出,全局变量在在每次被调用时都要获得锁,才能操作,因此保证了共享数据的安全性
Lock对比Rlock,死锁解决办法1
2
3lockA=threading.Lock()
lockB=threading.Lock()
lock = threading.Rlock()
生产者消费者模型
引入queue模块,解决锁的问题1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27# coding:utf-8
import threading
from queue import Queue
import time
q = Queue()
def action(arg):
    time.sleep(1)
    print  '子程序启动!the thread name is:%s\r' % threading.currentThread().getName()
    print 'the arg is:%s\r' %arg
    time.sleep(1)
def work():
    while q.qsize()>0:
        # 将数据从queue中取出来
        arg=q.get()
        action(arg)
if __name__ == '__main__':
    threadscount=4
    data=[1,2,3,4]
    # 将要传入的参数添加到queue中
    for i in data:
        q.put(i)
    for i in range(threadscount):
        t =threading.Thread(target=work)
        t.start()
    print '主程序完成!'
