全局变量是数据共享
各个线程是异步的
高计算用多进程--全局解释器锁GIL--同一时刻只能有一个线程被CPU执行
第一种方法—函数法:
import threading #线程库 import time def func(n): #线程函数 time.sleep(1) print('线程:',n) for i in range(10): t=threading.Thread(target=func,args=(i,)) #创建线程对象;func线程中要执行的函数;args=(1,)传递的参数(元组) t.start() #启动线程 print('主线程')
线程函数执行完毕,线程自动释放
第二种方法—类继承法:
import threading import time class mythread(threading.Thread):#继承threading.Thread def __init__(self,n): super().__init__() self.n=n def run(self): #线程要执行的函数;n是参数 time.sleep(1) print('子线程%s'%self.n) for i in range(10): t=mythread(i) #创建线程对象 t.start()
t.join() #等待t线程结束再继续执行
可以设置一个时间参数n:单位秒
当t是守护线程时,含义是主线程对于子线程等待n秒的时间将会杀死该子线程。简单的来说,就是给每个子线程一个n秒的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死
t不是守护线程时,主线程将会等待n秒时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束
t.setDaemon(True) 把子线程B设置为守护线程. 要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出, 必须在start() 方法调用之前设置
如果设置为false非守护线程,主线程退出时会等待子线程完毕才退出
线程的一些方法:
import threading import time def func(n): time.sleep(1) print('子线程',threading.current_thread()) #返回当前线程,是对象.<_MainThread(MainThread, started 17824)>;<Thread(Thread-1, started 17880)> print('子线程', threading.current_thread().name) #返回线程名称。MainThread;Thread-1 print('子线程', threading.current_thread().getName()) #返回线程名称。MainThread;Thread-1 for i in range(2): t=threading.Thread(target=func,args=(i,)) #创建线程对象;func线程中要执行的函数;args=(1,)传递的参数(元组) t.start() print('主线程',threading.current_thread()) print('主线程',threading.current_thread().name) print('主线程',threading.current_thread().getName()) print(t.isAlive()) #返回线程t是否还在执行 print(t.is_alive()) #返回线程t是否还在执行 print(threading.active_count()) #返回线程总数=主线程+子线程 print(threading.enumerate()) #返回所有线程对象。列表
线程递归锁Rlock:
互斥锁Lock只有一把钥匙
递归锁Rlock可以有n把钥匙
简言之:Lock属于全局,Rlock属于线程
import threading import time rlock1=rlock2=threading.RLock() #创建钥匙串,钥匙串中有两把锁 def eat1(name): rlock1.acquire() #上第一把锁;已经获得钥匙串,别的线程不能获取钥匙串了 print('%s拿了叉子'%name) time.sleep(1) rlock2.acquire() #上第二把锁,同一线程可以多次上锁 print('%s拿了面条' % name) time.sleep(1) print('%s开始吃面了' % name) rlock2.release() #释放钥匙 rlock1.release() def eat2(name): rlock2.acquire() print('%s拿了面条' % name) time.sleep(1) rlock1.acquire() print('%s拿了叉子' % name) time.sleep(1) print('%s开始吃面了' % name) rlock1.release() rlock2.release() t1=threading.Thread(target=eat1,args=('张一',)) t1.start() t2=threading.Thread(target=eat2,args=('张二',)) t2.start() t3=threading.Thread(target=eat1,args=('张三',)) t3.start() t4=threading.Thread(target=eat2,args=('张四',)) t4.start()
线程信号量--一段代码同时只能n个线程访问:
import threading,time def func(n,sem): sem.acquire() #上锁 print('线程%s开始'%n) time.sleep(1) print('线程%s结束' % n) sem.release() #放锁 sem = threading.Semaphore(3) #创建信号量,只允许3个线程访问 for i in range(10): threading.Thread(target=func,args=(i,sem)).start()
线程事件Event—设置阻塞非阻塞-控制线程:
#一个事件被创建之后,默认是阻塞状态 import threading e=threading.Event() #创建一个事件 print((e.is_set())) #e.is_set()返回事件的状态,False表示处于阻塞状态;True表示处于非阻塞状态。默认阻塞状态 e.set() #将e.is_set()的状态设置为True非阻塞状态 e.wait() #是否阻塞。e.is_set()的状态为False就处于阻塞状态;e.is_set()的状态为True就处于非阻塞状态 print('lm') e.clear() #将e.is_set()的状态设置为False阻塞状态 e.wait() #参数 n,表示最多等待n秒,n秒后往下继续执行 print('liming') #注意:事件在主线程和各子线程之间是共享的 #一个信号可以使所有的线程都进入阻塞状态 #也可以控制所有的线程解除阻塞
条件锁Condition:
import threading def func(con,i): con.acquire() #上锁 con.wait() #等待。线程挂起,直到收到一个notify通知或者超时(可选的,浮点数,单位是秒s)才会被唤醒继续运行。wait()必须在上锁前提下才能调用,否则会触发RuntimeError print('第%s个循环'%i) con.release() #释放锁 con=threading.Condition() #创建条件锁 for i in range(10): threading.Thread(target=func,args=(con,i)).start() #启动10个线程 while True: num=int(input('请输入数字:')) con.acquire() con.notify(num) #通知wait,允许非阻塞num次 con.release()
延时定时器Timer:
import threading def func(): print(100) t=threading.Timer(3,func) #创建定时器;参数1 等待n秒后线程开始执行;参数2 要执行的函数,参数3 args/kwargs: 方法的参数 t.start() #启动定时器 print('结束')