zoukankan      html  css  js  c++  java
  • python 35 多线程

    多线程

    1. 线程

    ​ 开启一个进程,操作系统会开辟一个进程空间,将进程的数据资源全部复制一份,然后cpu使线程执行代码。

    进程负责开辟空间、加载数据资源,线程负责执行。

    2. 线程vs进程

    	1. 开启进程的开销大;
    
    1. 开启进程的速度满,线程比进程快10—100倍;
      3. 同一进程的线程之间可共享数据,进程与进程之间使隔离的。

    线程的应用:多线程并发。比多进程并发开销小、速度快,可共享数据。

    3. 开启线程的两种方法。

    # 第一种方式
    from threading import Thread
    
    def task():
        print("===子线程")
    
    if __name__ == '__main__':		# 在windows下也可不写
        t1 = Thread(target=task)
        t1.start()
        print('===主线程')	
    """
    ===子线程
    ===主线程
    """
    
    # 第二种方式
    from threading import Thread
    
    class MyThread(Thread):
        
        def __init__(self, name)
        super().__init()
        self.name=name
    
        def run(self):
            print("==={self.name}子线程")
    
    if __name__ == '__main__':
        t1 = MyThread("meet")
        t1.start()
        print('===主线程')
    """
    ===meet子线程
    ===主线程
    """
    

    4. 线程的特性

    1. 同一进程中,每个线程的pid相同,因为它们在同一进程内。
    2. 主线程需等待其他子线程结束后,才能结束。(因为主线程结束代表本进程结束,而子线程需依赖进程存活。)
    3. 同一进程内的数据资源对于本进程的多个进程来说是共享的。

    5. 线程的相关方法

    Thread实例对象方法:
    	t.is_alive()(t.isAlive())	#判断线程是否活着
        t.getName()			# 获取线程名
        print(t.name)		# 获取线程名
        t.setName()			# 设置线程名
    
    threading模块方法:
    	currentThread()		# 获取当前线程的对象
        enumerate()			# 获取进程中所有线程对象,返回列表
        activeCount()		# 获取活跃的线程数量
    
    from threading import Thread,currentThread,enumerate,activeCount
    import time
    
    def task():
        time.sleep(1)
        print("is task")
    
    if __name__ == '__main__':
        t1 = Thread(target=task,name='===子线程')
        t1.start()
        print(t1.name)  # ===子线程
        print(t1.is_alive())    # True
        t1.setName('子线程')
        print(t1.getName())     # 子线程
    
        print(currentThread())    #主线程对象
        print(enumerate())      # 列表中两个线程对象 
        print(activeCount())    # 2
        print('===主线程')
    """
    True
    子线程
    <_MainThread(MainThread, started 14876)>
    [<_MainThread(MainThread, started 14876)>, <Thread(子线程, started 8736)>]
    2
    ===主线程
    is task
    """
    

    6. join 阻塞

    ​ 告知主线程需等待子线程执行结束后,再开始执行。

    from threading import Thread
    import time
    def sayhi(name):
        time.sleep(2)
        print('%s say hello' %name)
    
    if __name__ == '__main__':
        t=Thread(target=sayhi,args=('meet',))
        t.start()
        t.join()
        print(t.is_alive())
        print('主线程')
    '''
    meet say hello
    False
    主线程
    '''
    

    7. 守护线程 daemon

    若主线程运行结束,守护线程也会跟着结束。

    对主线程来说,运行完毕指的是本进程内所有非守护线程统统运行完毕,主线程才算运行完毕(若守护线程的生命周期小于其他的线程,会先结束)。

    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=True		# 设置t1为守护进程
        t1.start()
        t2.start()
        print("main---") 
    """
    123
    456
    main---
    end456
    """
    
    # 面试题---迷惑人的例子
    from threading import Thread
    import time
    
    def foo():
        print(123)  # 1
        time.sleep(1)
        print("end123")  # 4
    
    def bar():
        print(456)  # 2
        time.sleep(2)
        print("end456")  # 5
    
    if __name__ == '__main__':
    
        t1=Thread(target=foo)
        t2=Thread(target=bar)
        t1.daemon=True		# 设置t1为守护进程
        t1.start()
        t2.start()
        print("main-------")  # 3
        
    """
    123
    456
    main---
    end123		
    end456
    """
    # 因为bar需2s执行完毕,2s足够守护进程的foo执行完毕。因此在主线程结束前,守护线程以及结束。
    

    8. 互斥锁

    ​ 多线程的同步锁与多进程的同步锁是一个道理,就是多个线程抢占同一个数据(资源)时,我们要保证数据的安全,合理的顺序,因此需串行。

    from threading import Thread
    from threading import Lock
    import time
    import random
    
    x = 100
    
    def task(lock):
        global x
        lock.acquire()
        num = x
        time.sleep(random.random())
        x = num-1
        lock.release()
    
    if __name__ == '__main__':
        mutex = Lock()
        for i in range(100):
            t = Thread(target=task, args=(mutex,))
            t.start()
        time.sleep(2)
        print(f'主线程{x}')		# 输出不固定 串行执行
    
    
  • 相关阅读:
    U盘安装CentOS 7系统
    生产库中遇到mysql的子查询
    mysql 储存类型自增主键区别
    MySQL主从数据库同步延迟问题解决
    MySQL 加锁处理分析
    120篇精华文章打包送,干货慎入!
    mysql批量删除相同前缀的表和修改表名
    用pt-online-schema-change给大表在线加字段的时候导致从库数据丢失的问题
    【MySQL】online ddl 工具之pt-online-schema-change
    互联网公司为啥不使用mysql分区表?
  • 原文地址:https://www.cnblogs.com/yzm1017/p/11401436.html
Copyright © 2011-2022 走看看