python---多线程_主线程

全局变量是数据共享

各个线程是异步的

高计算用多进程--全局解释器锁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('结束')


python---多线程_主线程_02