一、线程
线程是操作系统能够进行运算调度的最小单位,是一串指令的集合。
它被包含在进程之中,是进程中的实际运作单位。
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
所有在同一进程里的线程是共享同一块内存空间的。
运行多线程需要频繁的cpu上下文切换。
注:cpu内一个核数只能同时运行一个线程,所以多核cpu同时可以运行多个线程。
在Python中,即使是多核cpu,同时运行的线程也只有一个,Python语言设计之初就不支持多核。
所以在Python程序中,启用越多的线程,程序不一定运行的就很快,因为cpu要进行大量的上下文切换,反而消耗时间;
GIL全局解释锁保障线程的上下文关系,保障当前只有一个线程在运行,与lock数据加锁无关。
1、threading模块
线程创建有2种方式:
直接调用
1 #!/user/bin/env ptyhon 2 # -*- coding:utf-8 -*- 3 # Author: VisonWong 4 5 import threading, time 6 7 def run(n): 8 print('Task',n) 9 time.sleep(2) 10 11 12 if __name__ == "__main__": 13 14 t1= threading.Thread(target=run,args=('t1',)) 15 t2= threading.Thread(target=run,args=('t2',)) 16 17 #两个同时执行,然后等待两秒程序结束 18 t1.start() 19 t2.start() 20 21 22 #程序输出 23 # Task t1 24 # Task t2
继承式调用
1 #!/user/bin/env ptyhon 2 # -*- coding:utf-8 -*- 3 # Author: VisonWong 4 5 import threading,time 6 7 class MyThread(threading.Thread): 8 9 def __init__(self,num): 10 # threading.Thread.__init__(self) 11 super(MyThread, self).__init__() 12 self.num = num 13 14 def run(self): #定义每个线程要运行的函数 15 print('running task',self.num) 16 time.sleep(2) 17 18 if __name__ == '__main__': 19 #两个同时执行,然后等待两秒程序结束 20 t1 = MyThread('t1') 21 t2 = MyThread('t2') 22 23 t1.start() 24 t2.start() 25 26 27 # 程序输出 28 # running task t1 29 # running task t2
2、join方法
join 等待线程执行完后,其他线程再继续执行。
1 #!/user/bin/env ptyhon 2 # -*- coding:utf-8 -*- 3 # Author: VisonWong 4 5 import threading, time 6 7 8 def run(n, sleep_time): 9 print("test...", n) 10 time.sleep(sleep_time) 11 print("test...done", n) 12 13 14 if __name__ == '__main__': 15 16 t1 = threading.Thread(target=run, args=("t1", 2)) 17 t2 = threading.Thread(target=run, args=("t2", 3)) 18 19 # 两个同时执行,然后等待t1执行完成后,主线程和子线程再开始执行 20 t1.start() 21 t2.start() 22 t1.join() # 等待t1 23 24 print("main thread") 25 26 27 # test... t1 28 # test... t2 29 # test...done t1 30 # main thread 31 # test...done t2
注: t1,t2同时执行,t1执行完后主程序才执行。
1 #!/user/bin/env ptyhon 2 # -*- coding:utf-8 -*- 3 # Author: VisonWong 4 5 import threading, time 6 7 8 def run(n): 9 print("task ",n ) 10 time.sleep(2) 11 print("task done",n) 12 13 start_time = time.time() 14 t_objs = [] #存线程实例 15 16 17 for i in range(10): 18 t = threading.Thread(target=run,args=("t-%s" %i ,)) 19 t.start() 20 t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里 21 22 for t in t_objs: #循环线程实例列表,等待所有线程执行完毕 23 t.join() 24 25 26 print("----------all threads has finished...") 27 print("cost:",time.time() - start_time) 28 29 30 # task t-0 31 # task t-1 32 # task t-2 33 # task t-3 34 # task t-4 35 # task t-5 36 # task t-6 37 # task t-7 38 # task t-8 39 # task t-9 40 # task done t-0 41 # task done t-1 42 # task done t-2 43 # task done t-3 44 # task done t-6 45 # task done t-5 46 # task done t-7 47 # task done t-4 48 # task done t-8 49 # task done t-9 50 # ----------all threads has finished... 51 # cost: 2.0041146278381348
注:计算所有线程运行的时间,待所有线程运行完后,运行主程序,计算运行时间。
3、Daemon
Daemon守护进程,主程序执行完毕时,守护线程会同时退出,不管是否执行完任务。