小结

上节课回顾

'''
### 抢票小案例优化, 基于磁盘做进程通讯(with open)
# start() 紧跟着join 变成了整体串行,保证了数据安全,降低了效率
# 进程锁 from multiprocessing import Lock  用进程锁的不同是只是针对处理数据的代码变成串行
    lock=Lock()
    传给子进程
    def 在子进程里面(lock):
        代码一
        代码二

        lock.acquire()
        处理数据
        lock.release()

### 进程通讯 ipc机制
# Queue 队列模块 实现
# 队列:管道+锁
# 管道:底层基于共享内存
from multiprocessing import Queue
q = Queue(maxsize)
q.put(obj) #如果队列满了,会阻塞在这里
q.get() #如果队列空了,会阻塞在这里

了解
block = False  不等了,满了或空了 直接报错
block = True  timeout = 's'(时间) ,超过这个时间就会报错

生产者消费者模型
吃包子案例
生产者---》队列(盆)---》消费者
生产者只需要不停的生产,达到了自己的最大效率
消费者也只要不停的消费,也达到自己的最大效率
生产者消费者模型,大大提高了生产者的生产效率,也大大提高了消费者的消费效率

JoinableQueue
底层维护了以计算器
q.put()  +1   task_done  -1
q.join() 当计数器不为0的时候会阻塞,当计数器为0时候不阻塞


##########今日内容##########
线程内容(*****)
线程的两种开启方式(*****)
线程vs进程 速度 内存是否共享(*****)
线程的join方法(*****)
单核下同一个进程的线程如何切换(***)
线程的其它方法(*)
守护线程(*)
'''

线程内容

'''
初识别线程:
在传统操作系统中:每个进程有一个地址空间,而且默认就有一个控制线程,cpu真正的执行单位是线程
在工厂中,每个车间都有房子,而且每个车间默认就有一条流水线

操作系统===》工厂
进程===》车间
线程===》流水线
cpu===>电源

线程:cpu最小的执行单位
进程:资源集合/资源单位
线程运行==代码运行
进程运行==各种资源+线程

右键运行:
申请内存空间,先把解释器代码丢进去并且把python代码丢进去(进程做的),运行代码(线程做的)

进程和线程的区别:

过程描述的区别:进程:申请内存空间,先把解释器代码丢进去并且把python代码丢进去(进程做的),运行代码(线程做的)
线程: p.start()直接开启线程,不需要申请空间

线程==》单指代码的执行过程
进程==》资源的申请与销毁的过程

进程内存空间批次隔离
线程:统一进程下的线程资源是共享的


进程和线程的创建速度
进程需要申请资源开辟空间  慢
线程只需要告诉操作系统一个执行方案  快

'''

线程开启的两种方式

### 方式一
# from threading import Thread
# import time
# def task():
#     print('子线程 start')
#     time.sleep(2)
#     print('子线程 end')
#
# if __name__ == '__main__':
#     t = Thread(target=task)
#     t.start() #告诉操作系统开启一个子线程
#     print('主线程')

###方式二
from threading import Thread
import time
class Myt(Thread):
    def run(self):
        print('子线程 start')
        time.sleep(2)
        print('子线程 end')
t = Myt()
t.start()
print('主线程')

### 进程会等到所有线程结束后才会结束

子线程vs子进程创建速度

from threading import Thread
from multiprocessing import Process
import time

def task(name):
    print(f'{name} start')
    time.sleep(2)
    print(f'{name} end')

if __name__ == '__main__':
    t = Thread(target=task, args=('子线程',))
    p = Process(target=task, args=('子进程',))
    #t.start()
    p.start()
    print('主')

'''
开启子线程的打印效果

子线程 start
主
子线程 end

开启子进程的打印效果

主
子进程 start
子进程 end


进程和线程的创建速度
开启子进程需要申请资源开辟空间  慢
开启子线程只是告诉操作系统一个执行方案  快

'''

子线程共享资源

from threading import Thread
import time, os

x = 100
def task():
    global x
    x = 50
    print(os.getpid()) #8576

if __name__ == '__main__':
    t = Thread(target=task)
    t.start()
    time.sleep(2)
    print(x) #50 成功修改了全局的x的值(说明线程是资源共享)
    print(os.getpid()) #8576

线程的join方法、

from threading import Thread
import time
def task():
    print('子线程 start')
    time.sleep(2)
    print('子线程 end')

if __name__ == '__main__':
    t = Thread(target=task)
    t.start()
    t.join() # 等待所有子线程结束后主线程才结束
    print('主线程')

线程的Join方法二

from threading import Thread
import time

def task(name, n):
    print(f'{name} start')
    time.sleep(n)
    print(f'{name} end')

if __name__ == '__main__':
    t = Thread(target=task, args=('线程1',1))
    t2 = Thread(target=task, args=('线程2', 2))
    t3 = Thread(target=task, args=('线程3', 3))

    start = time.time()
    t.start()
    t2.start()
    t3.start()
    t.join()
    t2.join()
    t3.join()
    end = time.time()
    print(end - start) #3.002171754837036
    print('主线程')

了解进程的join

from multiprocessing import Process
from threading import Thread
import time
def task():
    print('进程 开启')
    time.sleep(10)
    print('进程 结束')
def task2():
    print('子线程 开启')
    time.sleep(2)
    print('子线程 结束')

if __name__ == '__main__':
    p = Process(target=task)
    t = Process(target=task2)
    p.start()
    t.start()
    print('子进程join开始')
    p.join() # 主进程的主线程等待子进程运行结束
    print('主')

线程其它 相关用法

from threading import Thread, currentThread,enumerate,activeCount
import threading
import time

def task():
    print('子线程 start')
    time.sleep(2)
    print('子线程 end')
    print(enumerate())
    print(currentThread(),'子线程')

if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task)
    t1.start()
    t2.start()

    print(t1.is_alive()) #True
    print(t1.getName()) #Thread-1
    print(activeCount()) #3
    print(len(enumerate())) #3

守护线程

# 守护线程  守护的是进程的运作周期
from threading import Thread,enumerate,currentThread
import time

def task():
    print('守护线程开始')
    print(currentThread())
    time.sleep(20)
    print('守护线程结束')

def task2():
    print('子线程 start')
    time.sleep(5)
    print(enumerate())
    print('子线程 end')

if __name__ == '__main__':
    t1 = Thread(target=task)
    t2 = Thread(target=task2)
    t1.daemon = True
    t1.start()
    t2.start()
    print('主')