day 10 课堂笔记 线程的介绍(理论部分)

1.线程的介绍(理论部分)

1.1 进程线程分工

我们之间讲运行一个py文件,就是开启了一个进程,在内存中开辟一个进程空间,将必要的数据加载到这个进程空间中,然后CPU再去调用这个进程的主线程去执行具体的代码。一个进程里默认包含一个主线程。

进程是资源单位,线程是执行单位

a = 1
b = 2
c = a + b
if a:
	print(666)


def func():
	print(a - b)
	return


func()
print(111)

1.2 现实举例

工厂车间的例子

在这里插入图片描述

1.3 进程VS线程

  1. 开启线程的开销低于开启进程的开销
  2. 开启线程的速度远高于开启进程的速度,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用。
  3. 线程之间的数据时共享的,这样数据就不安全,进程之间的数据是隔离的。

1.4 多线程的应用举例

现在我们知道了,如果让你并发或者并行的执行任务,两种方式:

  • 开启多进程
  • 一个进程下开启多线程

img

文件编辑器:

第一个任务监听键盘的输入

第二个任务输入到屏幕显示器。

第三个任务实时将数据保存到磁盘上。

要用多线程执行:

  1. 多线程数据共享,避免进程通信的队列资源浪费。
  2. 开启多个进程开销大,效率相对低

2. 线程创建的两种方式

2.1 函数式创建线程

方法一:

from threading import Thread


def task(n1, n2):
	print(f'{n1}开始')
    print(f'{n2}结束')


if __name__ == "__main__":
	t1 = Thread(target=task, args=('小奶猿', '落叶'))
    t1.start()
    print('====主线程')

2.1.1 线程的开销小于进程

每次运行此代码,主线程永远在子线程开始之后再运行,并不是因为他们是串行,他们肯定是并行,只是因为开启线程的开销很低。

2.1.2 线程之间没有父子之分

线程之间没有主子。父子之分的,我们之所以称主线程、子线程仅仅是为了区分而已;而进程之间是有父子、主子之分,子进程的开启依赖于父进程,子进程的所有的资源都是深copy父进程而且父进程对子进程进行回收。

2.1.3 主进程为为什么要等其余线程结束后在结束。

进程是资源单位,加载各种数据资源的,但是如果进程里面的线程执行完毕,结束了,进程还有存在的必要吗?但是主进程如果也结束了,其余的线程怎么办?其余线程没有数据资源了,只能强制结束了,这样不合理、主线程代码执行完毕后,不能结束,要等待其余线程结束了,他在结束,这样进程在结束。

2.2 面向对象式创建线程

from threading import Thread


class MyThread(Thread):
    
    def run(self):
        print('子线程开始了')
        
        
if __name__ == '__main__':
    t1 = MyThread()
    t1.start()
    print('主')

3. 进程VS线程

  • 验证进程与线程的开启速度(开销)

    from threading import Thread
    import time
    
    
    def task(n1, n2):
        print(f'{n2}回来了。。。')
        time.sleep(2)
        print(f'{n1}心花怒放。。。')
    
        
    if __name__ == '__main__':
        t1 = Thread(target=task, args=('小奶猿', '落叶'))
        t1.start() # 线程课开销小,速度快。
        print('====线程')
    
  • 获取线程的pid

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

    一个进程下的所有的线程的pid都是这同一个进程的pid。

  • 同一个进程下的多线程共享数据。

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

    同一个进程下的多个线程一定是数据共享的。

4. 线程的其他方法

from threading import Thread
import threading
import time
import os


def task():
    print('子进程。。。')
    time.sleep(2)
  

if __name__ == '__main__':
    t1 = Thread(target=task, name='线程-1') # 设置线程的名字
    t2 = Thread(target=task, name='线程-2')
    t3 = Thread(target=task, name='线程-3')
    t1.start()
    t2.start()
    t3.start()
    """
    # t1.start()
    # print(t1.name)  # 获取线程的名字
    # t1.join()
    # print(t1.is_alive())  # 判断线程是否存活运行
    """
    print(threading.enumerate()) # 返回一个列表,存储的是当前活跃的线程对象。
    print(len(threading.enumerate())) # 获取当前活跃的线程数量
    print(threading.active_count()) # 获取当前活跃的线程的数量
    print('====主线程')

5.守护线程

  • 先回忆守护进程

    from multiprocessing import Process
    import time
    
    
    def foo():
        print(123)
        time.sleep(1)
        print('end123')
        
        
    def bar():
        print(456)
        time.sleep(3)
        print("end456")
        
        
    if __name__ == '__main__':
        p1 = Process(target=foo)
        p2 = Process(target=bar)
        p1.daemon = True
        p1.start()
        p2.start()
        print('main-------')
    

    总结:

    • 守护进程是等待主进程代码结束即结束。
  • 守护线程

    from threading import Thread
    import time
    
    
    def task(n1, n2):
        print(f'{n1}心花怒放。。。')
        time.sleep(2)
        print(f'{n2}回来了')
        
        
    if __name__ == '__main__':
        t1 = Thread(target=task, args=('小奶猿', '落叶'))
        t1.daemon = True
        t1.start()
        print('====主线程')
    
    • 再次测试

      from threading import Thread
      import time
      
      
      def foo():
          print(123)
          time.sleep(1)
          print('end123')
        
      
      def bar():
          print(456)
          time.sleep(3)
          print('end456')
        
      
      if __name__ == '__main__':
          t1 = Thread(target=foo)
          t2 = Thread(target=bar)
          t1.daemon = True
          t1.start()
          t2.start()
          print('main-----')
      

      守护线程要等待主线程的程序结束之后,在结束,主线程程序什么时候结束?主线程程序要等待其余的子线程结束之后再结束。

      守护线程要等待主线程以及其余的非守护线程的子线程全部结束之后,再结束。

      from threading import Thread
      import time 
      
      
      def foo():
          print(123)
          time.sleep(3)
          print('end123')
        
      
      def bar():
          print(456)
          time.sleep(1)
          print('end456')
        
      
      if __name__ == '__main__':
          t1 = Thread(target=foo)
          t2 = Thread(target=bar)
          t1.daemon = Ture
          t1.start()
          t2.start()
          print('main------')
      
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值