线程,协程
1. 线程的创建.
#线程的创建 from threading import Thread import time def sayhi(name): time.sleep(2) print("%s say hello"%name) if __name__ =="__main__": t =Thread(target=sayhi,args =("egon",)) t.start() print("主线程")
2.基于类创建线程
#通过类去创建线程. from threading import Thread import time class Sayhi(Thread): def __init__(self,name): super().__init__() self.name =name def run(self): time.sleep(2) print("%s say hello"%self.name) if __name__ == '__main__': t =Sayhi("egon") t.start() print("主线程")
打印结果:
主线程 (两秒后往下执行)
egon say hello
3. 多线程与多进程.
from threading import Thread from multiprocessing import Process import os,time def work(): print("hello",os.getpid()) if __name__ == '__main__': #part1:在主进程下开启多个线程,每个线程都跟主进程pid一样 t1 =Thread(target=work) t2 =Thread(target=work) t1.start() t2.start() print("主线程/主进程pid",os.getpid()) #part2:开启多个进程,每个进程都有不同的pid p1 =Process(target=work) p2 =Process(target=work) p1.start() p2.start() print("主线程/主进程pid",os.getpid())
线程的属性
Thread实例对象的方法 # isAlive(): 返回线程是否活动的。 # getName(): 返回线程名。 # setName(): 设置线程名。 threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
案例
from threading import Thread import threading from multiprocessing import Process import os def work(): import time time.sleep(3) print(threading.current_thread().getName()) if __name__ == '__main__': #在主进程下开启线程 t=Thread(target=work) t.start() print(threading.current_thread().getName()) print(threading.current_thread()) #主线程 print(threading.enumerate()) #连同主线程在内有两个运行的线程 print(threading.active_count()) print('主线程/主进程') 打印结果: MainThread <_MainThread(MainThread, started 104508)> [<_MainThread(MainThread, started 104508)>, <Thread(Thread-1, started 102040)>] 2 主线程/主进程 Thread-1
join方法
from threading import Thread import time def sayhi(name): time.sleep(2) print('%s say hello' %name) if __name__ == '__main__': t=Thread(target=sayhi,args=('egon',)) t.start() t.join() print('主线程') print(t.is_alive()) ''' egon say hello 主线程 False '''
打印结果: 三行代码经过2秒同时打印出来,(如果把join去掉的话,先打印主线程 ,然后记过两秒打印子线程.)
egon say hello
主线程
False
守护线程案例
from threading import Thread import time def sayhi(name): time.sleep(2) print('%s say hello' %name) if __name__ == '__main__': t=Thread(target=sayhi,args=('egon',)) t.setDaemon(True) #必须在t.start()之前设置 ,这段代码还没来得及子线程执行就已经结束了,所以只打印了结果的输出 t.start() print('主线程') print(t.is_alive()) 打印结果: 延时两秒打印如下内容 主线程 True
协程:
from greenlet import greenlet def eat(): print("eat start") g2.switch() print("eating end") g2.switch() def play(): print("play start") g1.switch() print("play end") g1 =greenlet(eat) g2 =greenlet(play) g1.switch()
from gevent import monkey;monkey.patch_all() import time import gevent def task(): time.sleep(1) print(12345) def sync(): for i in range(10): task() def async(): g_lst =[] for i in range(10): g =gevent.spawn(task) g_lst.append(g) gevent.joinall(g_lst) # for g in g_lst:g.join() sync() async()
打印结果: 前十个12345 一个一个输出,后10个一次性输出.
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
12345
协程案例。
import time import gevent def eat(): print("eating start") time.sleep(1) print("eating end") def play(): print("playing start") time.sleep(1) print("playing end") g1 =gevent.spawn(eat) g2 =gevent.spawn(play) g1.join() g2.join()
协程的应用
from gevent import monkey;monkey.patch_all() import gevent import requests import time def get_page(url): print('GET: %s' %url) response=requests.get(url) if response.status_code == 200: print('%d bytes received from %s' %(len(response.text),url)) start_time=time.time() gevent.joinall([ gevent.spawn(get_page,'https://www.python.org/'), gevent.spawn(get_page,'https://www.yahoo.com/'), gevent.spawn(get_page,'https://github.com/'), ]) stop_time=time.time() print('run time is %s' %(stop_time-start_time))