1.进程与线程
进程(有时被称为重量级进程)是程序的一次执行。每个进程都有自己的地址空间、内存、数据栈以及其它记录其运行轨迹的辅助数据。操作系统管理在其上运行的所有进程,并为这些进程公平地分配时间。进程也可以通过fork和spawn操作来完成其它的任务,不过各个进程有自己的内存空间、数据栈等,所以只能使用进程间通讯(IPC),而不能直接共享信息。 线程(有时被称为轻量级进程)跟进程有些相似,不同的是所有的线程运行在同一个进程中,共享相同的运行环境。它们可以想像成是在主进程或“主线程”中并行运行的“迷你进程”。线程有开始、顺序执行和结束三部分,它有一个自己的指令指针,记录自己运行到什么地方。线程的运行可能被抢占(中断)或暂时的被挂起(也叫睡眠)让其它的线程运行,这叫做让步。一个进程中的各个线程之间共享同一片数据空间,所以线程之间可以比进程之间更方便地共享数据以及相互通讯。线程一般都是并发执行的,正是由于这种并行和数据共享的机制使得多个任务的合作变为可能。实际上,在单CPU的系统中,真正的并发是不可能的,每个线程会被安排成每次只运行一小会,然后就把CPU让出来,让其它的线程去运行。在进程的整个运行过程中,每个线程都只做自己的事,在需要的时候跟其它的线程共享运行的结果。多个线程共同访问同一片数据不是完全没有危险的,由于数据访问的顺序不一样,有可能导致数据结果的不一致的问题,这叫做竞态条件。而大多数线程库都带有一系列的同步原语,来控制线程的执行和数据的访问。
2.使用
(1)简单例子 Python 的标准库中自带了多线程相关的模块,使在 python 中创建线程成了一件很简单的事。与线程相关的模块一共有两个:thread 和 threading。一般情况下我们只需要 threading 即可。 上面的代码中,我定义了一个 func 函数,然后在 main 函数中通过 for 循环创建了 4 个线程,然后通过将 target = func 的方式去告诉线程执行 func 函数,一切就绪后调用线程的 start 方法运行线程。结果如下:
HelloWorldHello WorldHello WorldHello World
(2)传参 在上面创建线程的例子其实是过于简单了,在我们实际的编程中给程序传递参数是必不可少的 (3)使用方法: thread包:
使用方法:_thread.start_new_thead(func_name, tuple) 参数两个,一个是需要运行的函数名,第二是函数的参数作为元祖使用,为空则使用空元祖 注意:如果函数只有一个参数,需要参数后由一个逗号 如_thread.start_new_thread(loop1,(“wjw”, ))
threading包: python3中常用的包
使用方法:t = threading.Thread(target=xxx, args=(xxx,)) t.start():启动多线程 t.join(): 等待多线程执行完成
线程常用属性:
- threading.currentThread:返回当前线程变量
- threading.enumerate: 返回一个包含正在运行的线程的list,正在运行的线程指的是线程启动后,结束前
- threading.activeCount: 返回正在运行的线程数量,效果跟len(threading.enumerate)相同
- thr.setName: 给线程设置名字
- thr.getName: 获得线程的名字
import time
import threading
def loop1():
# ctime 得到当前时间
print('Start loop 1 at :', time.ctime())
# 睡眠多长时间,单位是秒
time.sleep(6)
print('End loop 1 at:', time.ctime())
def loop2():
# ctime 得到当前时间
print('Start loop 2 at :', time.ctime())
# 睡眠多长时间,单位是秒
time.sleep(1)
print('End loop 2 at:', time.ctime())
def loop3():
# ctime 得到当前时间
print('Start loop 3 at :', time.ctime())
# 睡眠多长时间,单位是秒
time.sleep(5)
print('End loop 3 at:', time.ctime())
def main():
print("Starting at:", time.ctime())
# 生成threading.Thread实例
t1 = threading.Thread(target=loop1, args=( ))
# setName是给每一个子线程设置一个名字
t1.setName("THR_1")
t1.start()
t2 = threading.Thread(target=loop2, args=( ))
t2.setName("THR_2")
t2.start()
t3 = threading.Thread(target=loop3, args=( ))
t3.setName("THR_3")
t3.start()
# 预期3秒后,thread2已经自动结束,
time.sleep(3)
# enumerate 得到正在运行子线程,即子线程1和子线程3
for thr in threading.enumerate():
# getName能够得到线程的名字
print("正在运行的线程名字是: {0}".format(thr.getName()))
print("正在运行的子线程数量为: {0}".format(threading.activeCount()))
print("All done at:", time.ctime())
if __name__ == "__main__":
main()
# 一定要有while语句
# 因为启动多线程后本程序就作为主线程存在
# 如果主线程执行完毕,则子线程可能也需要终止
while True:
time.sleep(10)
继承thread的方法:
- 直接继承Thread
- 必须重写run函数,因为当类实例运行的时候就是在运行run函数
- 类实例可以直接运行
import threading import time
# 1. 类需要继承自threading.Thread
class MyThread(threading.Thread):
def __init__(self, arg):
super(MyThread, self).__init__()
self.arg = arg
# 2 必须重写run函数,run函数代表的是真正执行的功能
def run(self):
time.sleep(2)
print("The args for this class is {0}".format(self.arg))
for i in range(5):
t = MyThread(i)
t.start()
t.join()
print("Main thread is done!!!!!!!!")
threading.Timer:利用多线程在指定时间后调用一个函数
import threading
import time
def func():
print("I am running.........")
time.sleep(4)
print("I am done......")
if __name__ == "__main__":
t = threading.Timer(6, func)
t.start()
i = 0
while True:
print("{0}***************".format(i))
time.sleep(3)
i += 1
|