多线程的概念介绍
threading模块介绍:threading模块和multiprocessing模式在使用层面,有甚大的相似性
开启多线程的两种方式
开启进程的第一种方式:
#1.创建线程的开销比创建进程的开销小,因而创建线程的速度快
from multiprocessing import Process
from threading import Thread
import os
import time
def work():
print('<%s> is running'%os.getpid())
time.sleep(2)
print('<%s> is done'%os.getpid())
if __name__ == '__main__':
t=Thread(target=work,)
# t= Process(target=work,)
t.start()
print('主',os.getpid())
#开启进程的第一种方式
开启进程的第二种方式(用类):
from threading import Thread
import time
class Work(Thread):
def __init__(self,name):
super().__init__()
self.name = name
def run(self):
# time.sleep(2)
print('%s say hell'%self.name)
if __name__ == '__main__':
t = Work('egon')
t.start()
print('主')
#开启线程的第二种方式(用类)
在一个进程开启多个线程与在一个进程下开始多个子进程的区别:
线程的开启速度大于进程的开启速度
from multiprocessing import Process
from threading import Thread
import time
def work():
time.sleep(2)
print('hello')
if __name__ == '__main__':
t = Thread(target=work)#如果等上几秒,他会在开启的过程中先打印主,如果不等会先打印hello
# t = Process(target=work) #子进程会先打印主,
t.start()
print('主')
#线程的开启速度大于进程的开启速度
在同一个进程下开多个进程和开多个线程的pid不同
# 2.----------
from multiprocessing import Process
from threading import Thread
import os
def work():
print('hello',os.getpid())
if __name__ == '__main__':
#在主进程下开启多个线程,每个线程都跟主进程的pid一样
t1= Thread(target=work)
t2 = Thread(target=work)
t1.start()
t2.start()
print('主线程pid',os.getpid())
#来多个进程,每个进程都有不同的pid
p1 = Process(target=work)
p2 = Process(target=work)
p1.start()
p2.start()
print('主进程pid', os.getpid())
#在同一个进程下开多个进程和开多个线程的pid的不同
同一进程内的线程共享该进程的数据
from threading import Thread
from multiprocessing import Process
import os
def work():
global n
n-=1
print(n) #所以被改成99了
n = 100
if __name__ == '__main__':
# p = Process(target=work)
p = Thread(target=work) #当开启的是线程的时候,因为同一进程内的线程之间共享进程内的数据
#所以打印的n为99
p.start()
p.join()
print('主',n) #毫无疑问子进程p已经将自己的全局的n改成了0,
# 但改的仅仅是它自己的,查看父进程的n仍然为100
#同一进程内的线程共享该进程的数据
线程和进程的区别:
线程的一些方法
from threading import Thread
from threading import currentThread
from threading import enumerate
from threading import activeCount
import time
import os
def task():
time.sleep(2)
print('666')
if __name__ == '__main__':
t1 = Thread(target=task,name='线程1')
t2 = Thread(target=task,name='线程2')
t1.start()
t2.start()
print(t1.isAlive()) # 判断线程是否还在活动 返回布尔值
print(t1.getName()) # 获取线程名称
t1.setName('gou') # 设置线程名称
print(t1.name)
print(currentThread()) # 获取当前线程
print(enumerate()) # 获取当前进程下所有线程,并以列表形式返回
print(activeCount()) # 获取还在活动的线程数
print(f"==主线程{os.getpid()}")
# 结果:
True
线程1
gou
<_MainThread(MainThread, started 11472)>
[<_MainThread(MainThread, started 11472)>, <Thread(gou, started 1876)>, <Thread(线程2, started 8760)>]
3
==主线程12980
666
666
join和守护进程
join: 阻塞 告知主线程要等待我子线程执行完毕之后再执行主线程
from threading import Thread
import time
def task(name):
print(f'{name} is running')
time.sleep(1)
print(f'{name} is gone')
if __name__ == '__main__':
start_time = time.time()
t1 = Thread(target=task,args=('海狗',))
t2 = Thread(target=task,args=('海狗1',))
t3 = Thread(target=task,args=('海狗2',))
t1.start()
t1.join()
t2.start()
t2.join()
t3.start()
t3.join()
print(f'===主线程{time.time() - start_time}') # 线程是没有主次之分的.
# 结果:
海狗 is running
海狗 is gone
海狗1 is running
海狗1 is gone
海狗2 is running
海狗2 is gone
===主线程3.0049641132354736
守护线程:守护线程 等待非守护子线程以及主线程结束之后,结束.
from threading import Thread
import time
def sayhi(name):
print('你滚!')
time.sleep(2)
print('%s say hello' %name)
if __name__ == '__main__':
t = Thread(target=sayhi,args=('egon',))
# t.setDaemon(True) #必须在t.start()之前设置
t.daemon = True # 设置线程的两种方式
t.start() # 线程的开启速度要跟进程开很多
print('主线程')
# 结果:
'你滚!'
'主线程'
from threading import Thread
import time
def foo():
print(123) # 1
time.sleep(1)
print("end123") # 4
def bar():
print(456) # 2
time.sleep(3)
print("end456") # 5
t1=Thread(target=foo)
t2=Thread(target=bar)
t1.daemon=True
t1.start()
t2.start()
print("main-------") # 3
面试题
from threading import Thread
import time
def foo():
print(123) # 1
time.sleep(1)
print("end123") # 4
def bar():
print(456) # 2
time.sleep(3)
print("end456") # 5
t1=Thread(target=foo)
t2=Thread(target=bar)
t1.daemon=True
t1.start()
t2.start()
print("main-------") # 3
# 结果:
123
456
main-------
end123
end456
互斥锁
多个任务共抢一个数据,保证数据的安全的目的,要让其串行
from threading import Thread
import time
import random
x = 100
def task():
global x
temp = x
time.sleep(random.randint(1, 3))
temp = temp - 1
x = temp
if __name__ == '__main__':
l1 = []
for i in range(100):
t = Thread(target=task)
l1.append(t)
t.start()
for i in l1:
i.join()
print(f'主线程{x}')
# 结果: # 相当于对全局变量赋值100次99
主线程99
from threading import Thread
from threading import Lock
import time
import random
x = 100
def task(lock):
lock.acquire()
# time.sleep(random.randint(1,2))
global x
temp = x
time.sleep(0.01)
temp = temp - 1
x = temp
lock.release()
if __name__ == '__main__':
mutex = Lock()
l1 = []
for i in range(100):
t = Thread(target=task,args=(mutex,))
l1.append(t)
t.start()
time.sleep(3)
print(f'主线程{x}')
# 结果:
主线程0
原文:https://www.cnblogs.com/zhangdadayou/p/11431941.html