python学习第32天

Lexan 2020-06-12

一. Manager

进程之间的共享数据(列表list 或者 字典dict等)

from multiprocessing import Process,Manager,Lock

def work(data,lock):
   # 1.正常写法
   """
   lock.acquire()
   # data["count"] -= 1
   data[0] += 1
   lock.release()
   """
   
   # 2.使用with 语法简化上锁解锁操作
   with lock:
      data[0] += 1
   
if __name__ == "__main__":
   m = Manager()
   # 创建一个共享的字典
   data = m.dict( {"count":20000} )
   # 创建一个共享的列表
   data = m.list([1,2,3])
   
   # print(data)
   
   lst = []
   lock = Lock()
   for i in range(100):
      p = Process(target=work,args=(data,lock))
      p.start()
      lst.append(p)
      
   # 确保所有的进程执行完毕,然后在向下运行,打印数据,否则报错;
   for i in lst:
      i.join()
      
   print(data) # [101, 2, 3]

二. 线程

#进程是资源分配的最小单位
#线程是计算机中调度的最小单位

#线程的缘起
资源分配需要分配内存空间,分配cpu:
分配的内存空间存放着临时要处理的数据等,比如要执行的代码,数据
而这些内存空间是有限的,不能无限分配
目前配置高的主机,5万个并发已是上限.线程概念应用而生.

#线程的特点
线程是比较轻量级,能干更多的活,一个进程中的所有线程资源是共享的.
一个进程至少有一个线程在工作

1 . 一份进程资源中可以包含多个线程

from threading import Thread
from multiprocessing import Process
import os

"""
def func(num):
   print(‘当前线程{},所归属的进程id号{}‘.format(os.getpid(),num))

for i in range(10):
   # 异步创建10个子线程
   t = Thread(target=func,args=(i,))
   t.start()

# 主线程执行任务
print(os.getpid())

2 . 并发多线程和多进程, 多线程的速度更快,谨慎选择创建进程的数量

import time

def func(num):
   print(‘当前线程{},所归属的进程id号{}‘.format(os.getpid(),num))

if __name__==‘__main__‘:

   """
   #记录开始时间
   starttime=time.time()

   lst=[]
   for i in range(1000):
      t=Thread(target=func,args=(i,))
      t.start()
      lst.append(t)

   # 等到所有子线程执行完毕
   for i in lst:
      i.join()
      
   # 记录结束时间
   endtime=time.time()

   print("多线程执行时间:",endtime-starttime)
   """
   
   """
   #记录开始时间
   starttime=time.time()

   lst=[]
   for i in range(1000):
      p=Process(target=func,args=(i,))
      p.start()
      lst.append(p)

   # 等到所有子线程执行完毕
   for i in lst:
      i.join()
      
   # 记录结束时间
   endtime=time.time()

   print("多进程执行时间:",endtime-starttime)

3 .多线程共享同一份进程资源

num =1000
def func():
   global num
   num -=1

for i in range(1000):
   t=Thread(target=func)
   t.start()

print(num)

4 . 用自定义类的方法创建线程

一定要继承父类Thread

手动调用父类的构造方法

class MyThread(Thread):
   def __init__(self,name):
      # 手动调用父类的构造方法
      super().__init__()
      self.name = name

   def run(self):
      time.sleep(1)
      print("当前进程正在执行runing ... " , self.name)
      
if __name__ == "__main__":
   t = MyThread("机器今天会再次爆炸么?")
   t.start()
   print("主线程执行结束 ... ")

5 . 线程相关的函数

线程.is_alive()    检测线程是否仍然存在
线程.setName()     设置线程名字
线程.getName()     获取线程名字
1.currentThread().ident 查看线程id号 
2.enumerate()        返回目前正在运行的线程列表
3.activeCount()      返回目前正在运行的线程数量
def func():
   time.sleep(1)
if __name__ == "__main__":
   t = Thread(target=func)
   
   # print(t)
   t.start()
   # print(t , type(t))
   print(t.is_alive()) # False
   print(t.getName())
   t.setName("xboyww")
   print(t.getName())

currentThread().ident 查看线程id号

def func():
   print("子线程id",currentThread().ident  , os.getpid())

if __name__ == "__main__":
   Thread(target=func).start()
   print("主线程id",currentThread().ident , os.getpid())

enumerate() 返回目前正在运行的线程列表

acctiveCount() 返回目前正在运行的线程数量

from threading import enumerate
from threading import activeCount # (了解)
def func():
   print("子线程id",currentThread().ident  , os.getpid())
   time.sleep(0.5)
   
if __name__ == "__main__":
   for i in range(10):
      Thread(target=func).start()
   lst = enumerate()
   # 子线程10 + 主线程1个 = 11
   # print(lst ,len(lst))
   
   # 3.activeCount()      返回目前正在运行的线程数量
   print( activeCount() )

6 .守护线程

等待所有线程全部执行完毕之后,在自己终止,守护的是所有线程

线程名.setDaemon(True)

from threading import Thread
import time
def func1():
   while True:
      time.sleep(0.5)
      print("我是func1")
   
def func2():   
   print("我是func2 start ... ")
   time.sleep(3)
   print("我是func2 end ... ")
   
t1 = Thread(target=func1)
t2 = Thread(target=func2)

# 在start调用之前,设置守护线程
t1.setDaemon(True)

t1.start()
t2.start()

print("主线程执行结束 ... ")

7 . 用 Lock 保证数据安全

from threading import Lock,Thread
import time
n = 0

def func1(lock):
   global n
   
   lock.acquire()
   for i in range(1000000):
      # 方法一     
      n -= 1
   lock.release()
   
def func2(lock):
   global n
   # with 自动完成上锁+解锁
   with lock:
      for i in range(1000000):
         # 方法二           
         n += 1

# func1()
# func2()
# print(n)
if __name__ == "__main__":
   lst = []
   lock = Lock()
   
   time1 = time.time()
   for i in range(10):
      t1 = Thread(target=func1,args=(lock,))
      t2 = Thread(target=func2,args=(lock,))
      t1.start()
      t2.start()
      lst.append(t1)
      lst.append(t2)
      
   # 等待所有的子线程执行结束之后, 在打印数据
   for i in lst:
      i.join()
     
   time2 = time.time()
   print("主线程执行结束..." , n ,time2 - time1)

8 . 信号量 Semaphore(线程)

from threading import Semaphore,Thread
import time

def func(i,sm):
   with sm:
      print(i)
      time.sleep(3)

if __name__ == "__main__":
   sm = Semaphore(5)
   for i in range(20):
      Thread(target=func,args=(i,sm)).start()

"""
总结:
在创建线程的时候是异步创建
在执行任务的时候,因为Semaphore加了锁,所以线程之间变成了同步
"""

相关推荐