zoukankan      html  css  js  c++  java
  • python 线程基础

    线程基础
    # 线程基础
    """
    多任务的概念:就是操作系统可以同时运行多个任务
    并发:指的是任务数多余cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)
    并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的
    
    python的thread模块是比较底层的模块,python的threading是高级模块
    
    常用操作
    threading.currentThread(): 返回当前的线程变量。
    threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程
    threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果
    run(): 用以表示线程活动的方法
    start():启动线程活动
    join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生
    isAlive(): 返回线程是否活动的
    getName(): 返回线程名
    setName(): 设置线程名
    
    线程注意点
       使用threading模块时,往往会定义一个新的子类class,只要继承threading.Thread就可以了,然后重写run方法
       当线程的run()方法结束时该线程完成。
       多线程程序的执行顺序是不确定的  无法控制线程调度程序,但可以通过别的方式来影响线程调度的方式。
       每个线程默认有一个名字,python会自动为线程指定一个名字
       在一个进程内的所有线程共享全局变量,很方便在多个线程间共享数据
       线程是对全局变量随意遂改可能造成多线程之间对全局变量的混乱(即线程非安全)
       如果多个线程同时对同一个全局变量操作,会出现资源竞争问题,从而数据结果会不正确
       同步就是协同步调,按预定的先后次序进行运行。如:你说完,我再说。
       可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行;B执行,再将结果给A;A再继续操作。
    
    
    线程同步
       当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
       使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法
       对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间
       线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁
       某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;
       直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。
       互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性。
    
    hreading模块中定义了Lock类,可以方便的处理锁定
        # 创建锁
        mutex = threading.Lock()
        # 锁定
        mutex.acquire()
        # 释放
        mutex.release()
    
    锁的好处 确保了某段关键代码只能由一个线程从头到尾完整地执行
    锁的坏处 阻止了多线程并发执行  可能会造成死锁
    
    死锁
    在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源,就会造成死锁
    避免死锁
       程序设计时要尽量避免(银行家算法)
       添加超时时间等
    
    
    """
    
    # 多线程创建方式一
    import threading
    
    # threading.Thread(target=函数)  传名称即可
    
    
    def say():
        print("你好啊,python")
    
    
    for i in range(5):
        t = threading.Thread(target=say)
        t.start()  # 当调用start()时,才会真正的创建线程,并且开始执行
    
    # 主线程会等待所有的子线程结束后才结束
    import threading
    from time import sleep,ctime
    
    
    def sing():
        for i in range(3):
            print("正在唱歌...%d" % i)
            sleep(1)
    
    
    def dance():
        for i in range(3):
            print("正在跳舞...%d" % i)
            sleep(1)
    
    
    if __name__ == '__main__':
        print('---开始---:%s' % ctime())
    
        t1 = threading.Thread(target=sing)
        t2 = threading.Thread(target=dance)
    
        t1.start()
        t2.start()
    
        sleep(5)  # 屏蔽此行代码,试试看,程序是否会立马结束?
        print('---结束---:%s' % ctime())
    
    # 查看线程数量
    import threading
    from time import sleep,ctime
    
    def sing():
        for i in range(3):
            print("正在唱歌...%d" % i)
            sleep(1)
    
    def dance():
        for i in range(3):
            print("正在跳舞...%d" % i)
            sleep(1)
    
    if __name__ == '__main__':
        print('---开始---:%s' % ctime())
    
        t1 = threading.Thread(target=sing)
        t2 = threading.Thread(target=dance)
    
        t1.start()
        t2.start()
        alength = threading.activeCount()
        print("活动线程数量是:%s" % alength)
        while True:
            # length = len(threading.enumerate())  # 返回一个包含正在运行的线程的list列表
            # print('运行的线程数为:%d' % length)
            # if length <= 1:
            #     break
    
            alength = threading.activeCount()
            print("活动线程数量是:%s" % alength)  # 返回正在运行的线程数量  threading.activeCount() == len(threading.enumerate())
            if alength <= 1:
               break
    
            sleep(0.5)
    
    # 线程的执行顺序 不能确定
    import threading
    import time
    
    class MyThread(threading.Thread):
        def run(self):
            for i in range(3):
                time.sleep(1)
                msg = "I'm "+self.name+' @ '+str(i)
                print(msg)
    def test():
        for i in range(5):
            t = MyThread()
            t.start()
    if __name__ == '__main__':
        test()
    
    # 线程执行代码的封装
    import threading
    import time
    
    class MysThread(threading.Thread):
        def run(self):
            for i in range(3):
                time.sleep(1)
                msg = "I'm "+self.name+' @ '+str(i)  # name属性中保存的是当前线程的名字
                print(msg)
    
    
    if __name__ == '__main__':
        t = MysThread()
        t.start()
    
    # 多线程数据是共享的
    from threading import Thread
    import time
    
    g_num = 100
    
    def work1():
        global g_num
        for i in range(3):
            g_num += 1
    
        print("----in work1, g_num is %d---"%g_num)
    
    
    def work2():
        global g_num
        print("----in work2, g_num is %d---"%g_num)
    
    
    print("---线程创建之前g_num is %d---"%g_num)
    
    t1 = Thread(target=work1)
    t1.start()
    
    # 延时一会,保证t1线程中的事情做完
    time.sleep(1)
    
    t2 = Thread(target=work2)
    t2.start()
    
    # 互斥锁 -- 解决数据共享出现的问题
    import threading
    import time
    
    g_num = 0
    
    def test1(num):
        global g_num
        for i in range(num):
            mutex.acquire()  # 上锁
            g_num += 1
            mutex.release()  # 解锁
    
        print("---test1---g_num=%d"%g_num)
    
    def test2(num):
        global g_num
        for i in range(num):
            mutex.acquire()  # 上锁
            g_num += 1
            mutex.release()  # 解锁
    
        print("---test2---g_num=%d"%g_num)
    
    # 创建一个互斥锁
    # 默认是未上锁的状态
    mutex = threading.Lock()
    
    # 创建2个线程,让他们各自对g_num加1000000次
    p1 = threading.Thread(target=test1, args=(1000000,))
    p1.start()
    
    p2 = threading.Thread(target=test2, args=(1000000,))
    p2.start()
    
    # 等待计算完成
    while len(threading.enumerate()) != 1:
        time.sleep(1)
    
    print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
    
    # udp 聊天
    import socket
    import threading
    # 接收信息
    def recvs(udp_socket):
        while True:
            back = udp_socket.recvfrom(1024)
            msg = back
            print(msg)
    
    # 发送信息
    def sends(udp_socket, dest_ip, dest_port):
        while True:
            msg = input("请输入你要发送的信息:")
            if msg == 'exit':
                break
            udp_socket.sendto(msg.encode(), (dest_ip, dest_port))
    
    # udp主函数
    def main():
        udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        udp_socket.bind(('', 8001))
    
        dest_ip = input("请输入对方的ip:")
        dest_port = int(input("请输入对方的port:"))
    
        t1 = threading.Thread(target=sends, args=(udp_socket, dest_ip, dest_port))
        t2 = threading.Thread(target=recvs, args=(udp_socket,))
    
        t1.start()
        t2.start()
    
    
    if __name__ == '__main__':
        main()
  • 相关阅读:
    构建之法
    第一阶段SCRUM冲刺
    NABCD项目分析
    结对开发
    梦断代码阅读-04
    梦断代码阅读-05
    移动端疫情展示
    用Python爬取疫情数据
    全球疫情可视化地图
    第二阶段冲刺第三天个人记录
  • 原文地址:https://www.cnblogs.com/ddf128/p/12028658.html
Copyright © 2011-2022 走看看