102
多任务 同一时间多个任务执行 多个进程
操作系统可以同事运行多个任务 多核的cpu已经非常的普及
单核的cpu也可以执行多个任务
print("Hello, Wo rld!");
'''子线程创建步骤
1 导入模块 threading
2 使用threading.thread()创建对象 (子线程对象)
3 指定子线程执行的分支
4 启动子线程 线程对象.start()
'''
import time
import threading
def saysorry():
print("sorry")
time.sleep(0.5)
if __name__ == "__main__":
for i in range(5):
th_obj = threading.Thread(target=saysorry)\
th_obj.start()
print("111111111111111111")
-----------------------------------------------------------------------------------------------
import time
import threading
def sing():
for i in range(5):
print ("sing")
def dance():
for i in range(5):
print ("dance")
if __name__ == "__main__":
for i in range(5):
th_obj_sing = threading.Thread(target=sing)
th_obj_dance = threading.Thread(target=dance)
th_obj_sing.start()
th_obj_dance.start()
print("111111111111111111")
主线程的作用是创建子线程
等子线程结束才关闭
子线程 程序的一个分支
导入模块 import threading
创建对象 threading.Thread(target=funcname)
启动子线程对象 线程对象.start()
----------------------------------------------------------------------------------
线程的数量
如何查看线程的数量
threading.enumerate()获取当前所有活跃的线程数量
args=(参数1,参数2,。。。。)
元祖与字典混合时 元祖后面加上一个逗号
线程是被系统独立调度和分派的最小系统
无法控制线程调度程序 但可以通过别的方式来影响线程调度的方式
说明:多线程程序的执行顺序是不确定的,当执行到sleep语句的时候,线程被阻塞blocked
,到sleep结束后,线程进入就绪runnable状态,等待调度 而线程调度将自行选择一个线程执行。
线程参数
元祖
threading.tread(targer=xxxx,agrs=(param1,param2...))
字典
threading.tread(targer=xxxx,kwargs=(参数1:param1,参数2:param2...))
混合
threading.tread(targer=xxxx,agrs=(param1,param2,...,),kwargs=(参数1:param1,参数2:param
线程的顺序
线程执行无法 由cpu自己算法调度 程序员无法控制
------------------------------------------------------------------------------------------
线程的守护 守护线程
能够使用setDaemon 设置子线程守护主线程
子线程在主线程的时候自动退出
import time
import threading
def work1():
for i in range(10):
print("正在执行work1.。。。。")
time.sleep(0.5)
if __name__=="__main__":
thread_work= threading.Thread(target=work1)
thread_work.setDaemon(True)
thread_work.start()
time.sleep(2)
print("over !!!!!!")
exit()
---------------------------------------------------------------------------------------------
你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。
你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。
你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。
并发的关键是你有处理多个任务的能力,不一定要同时。
并行的关键是你有同时处理多个任务的能力。
所以我认为它们最关键的点就是:是否是『同时』。
做并发编程之前,必须首先理解什么是并发,什么是并行,什么是并发编程,什么是并行编程。
并发(concurrency)和并行(parallellism)是:
解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
解释三:并行是在多台处理器上同时处理多个任务,如hadoop分布式集群。并发是在一台处理器上“同时”处理多个任务。
当一个计算机 多个任务的时候其实就是让操作系统轮流让各个任务交替执行
雨露均沾
2.8G 2.8亿次
并发 指的是任务数大于cpu核数
并行 任务数小于cpu核数 即任务一块执行
并发:任务数大于cpu核心数
并行:任务数小于或等于cpu的核心数
---------------------------------------------------------------------------------------
自定义线程类
通过集成threading.Thread 可以实现自定义线程
方法:
让自定义类继承 threading.thread类
重写父类(threading.Thread) run 方法
通过创建子类对象 让子类对象.start()就可以启动子线程
import time
import threading
'''
def run():
pass
def start():
'''
class mythread11(threading.Thread):
def __init__(self,num):
super().__init__()
self.num = num
def run(self):
for i in range(8):
print("正在执行子线程run方法...",i," ",self.name," ",self.num)
time.sleep(0.5)
if __name__=="__main__":
myth = mythread11(10)
myth.start()
print("xxxxxxxxxxx")
'''
导入模块
创建类并且继承threading.Thread
calss mythread(threading.Thread)
重写父类的方法
def run(self)
...
创建对象并且调用.start()
myth = mythread()
mythread.start()
底层原理
Thread类
run方法
start()
start中调用run方法
自定义线程类的init方法问题
子类先通过super调用父类的初始化方法 子类再初始化
def __init__(self,num):
#先调用父类的init方法
super().__init__()
self.num =num
'''
--------------------------------------------------------------------
import threading
import time
num =0
def work1():
global num
for i in range(10000000):
num +=1
print("work1 num =",num)
def work2():
global num
for i in range(10000000):
num +=1
print("work2 num =",num)
if __name__ == "__main__":
t1 = threading.Thread(target = work1)
t2 = threading.Thread(target = work2)
t1.start()
t1.join()
t2.start()
while len(threading.enumerate())!=1:
time.sleep(1)
print("main-------------",num)
------------------------------------------------------------------------------
'''
三大步骤
创建一把锁
lock1 = threading.Lock()
上锁
lock1.acquire()
解锁
lock1.release()
'''
'''
当多个线程几乎同时修改某一个共享数据的时候 需要进行同步控制
线程同步可以保证几个线程安全访问竞争资源 最简单的同步机制是引入互斥锁
互斥锁为资源引入一个状态 锁定/非锁定
某线程要更改共享数据时,先将其锁定
threading 模块中定义了lock锁 可以方便的处理锁定
创建锁
mutex = threading.lock()
锁定
mutex.acquire()
释放
mutex.release()
如果这个锁之前没有加上锁的 那么acquire不会堵塞的
如果在调用acquire对这个锁之前 他已经被其他线程上了锁 那么此时acquire会堵塞 直到这个锁被解锁为止
使用互斥锁对同一变量进行两百万加法的操作
'''
'''
过程:
创建一把互斥锁
在使用资源之前要锁定
使用完资源后 要解锁释放
'''
import threading
import time
num =0
def work1():
global num
lock1.acquire()
for i in range(2000000):
num +=1
lock1.release()
print("work1 num =",num)
def work2():
global num
lock1.acquire()
for i in range(100000):
num +=1
lock1.release()
print("work2 num =",num)
if __name__ == "__main__":
lock1= threading.Lock()
t1 = threading.Thread(target = work1)
t2 = threading.Thread(target = work2)
t1.start()
t2.start()
while len(threading.enumerate())!=1:
time.sleep(1)
print("main-------------",num)
--------------------------------------------------------------------------------------
死锁
print("Hello, World!")
'''
死锁会造成应用停止
'''
import threading
def get_value(index):
list_data=[11111,21111,311111,411111,5111111]
lock1.acquire()
if index >= len(list_data):
print( "下标越界,",index)
return
print(list_data[index])
lock1.release()
if __name__ =="__main__":
lock1 = threading.Lock()
for i in range(10):
t1 = threading.Thread(target=get_value, args=(i,))
t1.start()
'''
互斥锁的步骤
创建一把锁
lock1.threading.Lock()
上锁
lock1.acquire()
解锁
lock1.release()
互斥锁的使用原则 尽可能的减少锁定竞争资源
死锁:在多线程中,两个线程占用一些资源,而且同一时间都在等待对方释放资源,这种状态就是死锁状态
避免:锁使用完毕后 要及时的释放
死锁要满足四个条件 锁的不是线程 而是共享的资源
'''
|