Python并发编程04/多线程

Python并发编程04/多线程

1.生产消费者模型

#编程思想,模型,设计模式,理论等等,都是交给你一种编程的方法,以后你遇到类似的情况,套用即可.
生产者消费者模型三要素:
#   生产者: 产生数据的
#   消费者: 接收数据做进一步处理的
#   容器: 盆(队列)
队列容器的作用:
#起到缓冲的作用,平衡生产力与消费力,解耦.

# from multiprocessing import Process
# from multiprocessing import Queue
# import time
# import random
#
# def producer(q,name):
#     for i in range(1,6):
#         time.sleep(random.randint(1,2))
#         res = f'{i}号包子'
#         q.put(res)
#         print(f'生产者{name} 生产了{res}')
#
#
# def consumer(q,name):
#     while 1:
#         try:
#             food = q.get(timeout=3)
#             time.sleep(random.randint(1, 3))
#             print(f'\033[31;0m消费者{name} 吃了{food}\033[0m')
#         except Exception:
#             return
#
# if __name__ == '__main__':
#     q = Queue()
#     p1 = Process(target=producer,args=(q,'小白'))
#     p2 = Process(target=consumer,args=(q,'小黑'))
#     p1.start()
#     p2.start()

2.线程的理论知识

2.1什么是线程

#一条流水线的工作流程.
#进程: 在内存中开启一个进程空间,然后将主进程的所有的资源数据复制一份,然后调用cpu去执行这些代码.
#之前的描述不够具体:
#开启一个进程: 
#在内存中开启一个进程空间,然后将主进程的所有的资源数据复制一份,然后调用线程去执行代码
***进程是资源单位, 线程是执行单位.
标准描述开启一个进程:
    开启一个进程:进程会在内存中开辟一个进程空间,将主进程的资料数据全部复制一份,线程会执行里面的代码.

2.2线程vs进程

#1. 开启进程的开销非常大,比开启线程的开销大很多.
#2. 开启线程的速度非常快.要快几十倍到上百倍.
#3. 同一进程线程与线程之间可以共享数据,进程与进程之间需借助队列等方法实现通信.

2.3线程的应用

#1. 并发: 一个cpu 看起来像是同时执行多个任务.
#   单个进程开启三个线程.并发的执行任务.
#   开启三个进程并发的执行任务.
#   文本编辑器:
#      1. 输入文字.
#      2. 在屏幕上显示.
#      3. 保存在磁盘中.
#
#   开启多线程就非常好了: 
#       数据共享, 开销小,速度快.
#主线程子线程没有地位之分,但是,一个进程谁在干活? 一个主线程在干活,当干完活了,你得等待其他线程干完活之后,才能结束本进程.

3.开启进程的两种方式

3.1第一种方式

# 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__':
#
#     t1 = Thread(target=task,args=('二狗',))
#     t1.start()
#     print('===主线程')  # 线程是没有主次之分的.

3.2第一种方式

# from threading import Thread
# import time
#
# class MyThread(Thread):
#
#     def __init__(self,name,l1,s1):
#         super().__init__()
#         self.name = name
#         self.l1 = l1
#         self.s1 = s1
#     def run(self):
#         print(f'{self.name} is running')
#         time.sleep(1)
#         print(f'{self.name} is gone')
#
# if __name__ == '__main__':
#     t1 = MyThread('二狗', [1,2,3], '180')
#     t1.start()
#     print('=====主线程')

4.线程vs进程的代码对比

4.1开启速度对比

多进程

# from threading import Thread
# from multiprocessing import Process
# import os
#
# def work():
#     print('hello')
#
# if __name__ == '__main__':
#     #在主进程下开启线程
#     t=Process(target=work)
#     t.start()
#     print('主线程/主进程')

多线程

# 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__':
#
#     t1 = Thread(target=task,args=('二狗',))
#     t1.start()
#     print('===主线程')  # 线程是没有主次之分的.

4.2对比pid

进程

# from multiprocessing import Process
# import time
# import os
# def task(name):
#     print(f'子进程: {os.getpid()}')
#     print(f'主进程: {os.getppid()}')
#
# if __name__ == '__main__':
#
#     p1 = Process(target=task,args=('二狗',))  # 创建一个进程对象
#     p2 = Process(target=task,args=('二狗',))  # 创建一个进程对象
#     p1.start()
#     p2.start()
#     print(f'==主{os.getpid()}')

线程

# from threading import Thread
# import os
#
# def task():
#     print(os.getpid())
#
# if __name__ == '__main__':
#
#     t1 = Thread(target=task)
#     t2 = Thread(target=task)
#     t1.start()
#     t2.start()
#     print(f'===主线程{os.getpid()}')

4.3同一个进程内线程共享内部数据

# from threading import Thread
# import os
#
# x = 3
# def task():
#     global x
#     x = 100
#
# if __name__ == '__main__':
#
#     t1 = Thread(target=task)
#     t1.start()
#     t1.join()
#     print(f'===主线程{x}')

同一进程内的资源数据对于这个进程的多个线程来说是共享的.

5.线程的其他方法

# from threading import Thread
# from threading import currentThread
# from threading import enumerate
# from threading import activeCount
# import os
# import time
#
# def task():
#     # print(currentThread())
#     time.sleep(1)
#     print('666')
# if __name__ == '__main__':
#
#     t1 = Thread(target=task,name='线程1')
#     t2 = Thread(target=task,name='线程2')
#     # name 设置线程名
#     t1.start()
#     t2.start()
#     # time.sleep(2)
#     # print(t1.isAlive())  # 判断线程是否活着
#     # print(t1.getName())  # 获取线程名
#     # t1.setName('子线程-1')
#     # print(t1.name)  # 获取线程名  ***
#
#     # threading方法
#     # print(currentThread())  # 获取当前线程的对象
#     # print(enumerate())  # 返回一个列表,包含所有的线程对象
#     print(activeCount())  # ***
#     print(f'===主线程{os.getpid()}')

6.join与守护线程

6.1join

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}')  # 线程是没有主次之分的.

6.2守护线程

# 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
结果:
123
456
main-------
end123
end456
守护线程 等待非守护子线程以及主线程结束之后,结束.
# from threading import Thread
# import time
#
# def foo():
#     print(123)  # 1
#     time.sleep(3)
#     print("end123")  # 4
#
# def bar():
#     print(456)  # 2
#     time.sleep(1)
#     print("end456")  # 5
#
# t1=Thread(target=foo)
# t2=Thread(target=bar)
#
# t1.daemon=True
# t1.start()
# t2.start()
# print("main-------")  # 3

7.互斥锁

# 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}')
多个任务公抢一个数据,保证数据的安全的目的,要让其串行

# 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()
#
#     for i in l1:
#       i.join()
#     print(f'主线程{x}')

猜你喜欢

转载自www.cnblogs.com/liubing8/p/11403483.html