多线程模块(threading)

#!/usr/bin/env python
# coding=utf-8

import threading
import time

'''
Python中的多线程并不是真正的多线程,是利用GIL(Global Interpreter Lock,全局解释器锁)来实现的多线程,本质上仍然是单线程。
GIL的工具流程是:
设置GIL->开始一个线程->执行一定量的任务,然后程序主动让出控制权(sleep等)->把线程设置为休眠状态->解锁GIL->如此循环回到开始的设置GIL
Python的多线程模块有thread和threading,推荐使用threading。因为在thread模块中,线程与主线程之间的同步问题要自行管理。
在threading模块中,这些同步问题已经作好了相关的封装,不需要管理同步问题。
'''

'''
https://docs.python.org/2/library/threading.html

threading模块中提供的函数有:
threading.active_count(), threading.activeCount():返回活着的线程数,数值上等于enumerate()返回的列表的长度。
threading.Condition():工厂函数,返回一个条件变量对象。条件变量允许一个或多个线程处于等待状态,直到被其它线程唤醒。
threading.current_thread(),threading.currentThread():返回当前线程对象。如果调用者的线程控制不是由threading创建的,则会创建一个功能有限的虚拟线程。
threading.enumerate():返回活着的线程对象列表,包括守护线程、虚拟线程(由current_thread()产生的)和主线程。已经终止的线程和未开始的线程排除在外。
threading.Event():返回一个事件对象。
threading.Lock():返回原始锁对象。如有线程获取了它,此后想再获取的都会处于阻塞,直到它被释放。任意线程都可以释放它。
threading.RLock():返回可重获锁对象(Reentrant Lock Object)。要释放它,只能由获取它的线程来释放。同一线程可以再次获取而不会阻塞,但获取了多少次就要有多少次释放的动作。
threading.Semaphore([value]):返回信号量对象。信号量管理一个计数量,这个计数量是调用release()的次数减去调用acquire()的次数再加上一个初始值value(默认为1)。如果计数器为负值,acquire()在必要时会阻塞。
threading.BoundedSemaphore([value]):返回有界的信号量对象。有界信号量是用于当前值不超过初始值(默认为1)。如果超过,抛出ValueError异常。大多数情况,信号量是用来保证资源的有限容量,如果信号量被释放次数过多,就有bug的迹象。
threading.settrace(func):为所有由threading创建的线程添加追踪函数。追踪函数func会在每个线程调用run()之前传递给 sys.settrace()。
threading.setprofile(func):为所有由threading创建的线程添加配置函数。配置函数func会在每个线程调用run()之前传递给 sys.setprofile()。
threading.stack_size([size]):返回当新建线程时的堆栈大小。如果指定size,由此size用于后续创建的线程。size的值必须为0或一个大于32768(32KB)的整数。32KB是GIL自身得到保证的最小堆栈空间。如果size指定了一个不支持的值,抛出ThreadError异常;如果size无效,抛出ValueError异常。
'''

'''
threading模块中提供的类有:
class threading.local:线程局部数据类。使用时实例化一个对象,然后保存属性到这个对象。保存的属性对不同的线程是独立存在的。
class threading.Thread:线程控制类。
class threading.Timer:也是一个线程类,用于在指定时间后执行指定函数。
class threading.Lock:原始锁类。
class threading.RLock:可重获锁类。
class threading.Condition:条件变量类。
class threading.Semaphore:信号量类。
class threading.BoundedSemaphore:有界信号量类。
class threading.Event:事件类。
'''

'''
线程异常:
exception threading.ThreadError:线程相关的异常。很多接口使用RuntimeError,而不是ThreadError。
'''

'''
线程类Thread
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})
group:保留为以后所用,用None即可
target:可调用目标,会在run()中调用
name:进程名,默认为Thread-#
args:传入target的参数元组
kwargs:传入target的参数字典

属性:
name:线程名,多个线程可能同名
daemon:是否为守护线程,要在start()之前设置才有效
ident:线程标识,如线程未开始则为None

方法:
start():开始线程,线程开始后,会自动运行run()
run():线程执行任务入口
join([timeout]):父线程要等待调用join的线程结束之后才能运行,或等待timeout时间
is_alive(),isAlive():线程是否还活着
getName():返回线程名
setName():设置线程名,参考name属性
isDaemon():是否为守护线程
setDaemon():设置守护线程,参考daemon属性
'''
def loop_thread(name, sec):
    print u'开始循环{} 时间点:{}\n'.format(name, time.ctime())
    time.sleep(sec)
    print u'循环结束{} 时间点:{}\n'.format(name, time.ctime())


def run_loop_thread():
    loops = ['A', 'B']
    ts = [3, 5]
    n = len(loops)
    threads = []
    print u'所有线程开始时间:{}\n'.format(time.ctime())
    for i in range(n):
        t = threading.Thread(target=loop_thread, args=(loops[i], ts[i]))
        threads.append(t)
    for t in threads:
        t.start()
    for t in threads:
        t.join()
    print u'所有线程结束时间:{}'.format(time.ctime())


'''
原始锁类Lock

方法:
Lock.acquire([blocking]):获取锁,blocking为True时,获取不到则阻塞,直到获得为止
Lock.release():释放锁
'''

'''
可重获取锁类RLock

方法:
RLock.acquire([blocking]):获取锁,blocking为True时,获取不到则阻塞,直到获得为止。如果当前线程已经拥有锁,再去获取,再增加锁的递归层数
RLock.release():释放锁,减少递归层数
'''

'''
条件Condition
class threading.Condition([lock])
lock:如果为None,则新建一个Lock或RLock对象作为底层的锁

方法:
acquire(*args):获取底层锁
release():释放底层锁
wait([timeout]):线程等待此条件直到被唤醒或timeout时间到
notify(n=1):唤醒n个等待此条件的线程
notify_all(),notifyAll():唤醒所有等待此条件的线程
'''

'''
信号量类Semaphore
class threading.Semaphore([value])
value:内部计数器的初始值,默认为1。给0的话,抛出ValueError异常

方法:
acquire([blocking]):获取信号量
release():释放信号量,内部计数器加1,
'''

'''
事件类Event
class threading.Event
线程简单的通过机制。一个线程发出事件信号,另一个线程等待事件信号。内部标帜初始为False

方法:
is_set(),isSet():当内部标帜为True时返回True
set():设置内部标帜为True
clear():设置内部标帜为False
wait([timeout]):等待直到内部标帜为True,或timeout时间到。
'''

'''
计时器类Timer
class threading.Timer(interval, function, args=[], kwargs={})
interval:计时时间,单位为秒
function:执行的函数
args:function的列表参数
kwargs:function的字典参数

方法:
cancel():停止计时器
'''


if __name__ == '__main__':
    run_loop_thread()

'''
输出为:

所有线程开始时间:Fri Jun 28 10:07:43 2019

开始循环A 时间点:Fri Jun 28 10:07:43 2019

开始循环B 时间点:Fri Jun 28 10:07:43 2019

循环结束A 时间点:Fri Jun 28 10:07:46 2019

循环结束B 时间点:Fri Jun 28 10:07:48 2019

所有线程结束时间:Fri Jun 28 10:07:48 2019
'''

源码可于github下载:https://github.com/gkimeeq/PythonLearning

posted @ 2019-06-28 10:45  gkimeeq  阅读(350)  评论(0编辑  收藏  举报