python之线程学习(一)

    技术2022-08-11  83

    线程

    多任务多任务介绍多任务理解多任务的实现方式 线程线程介绍线程的使用使用join()方法的使用setDaemon()方法的使用enumerate()的使用,查看线程数量子线程的创建与执行 继承Thread类创建线程多线程共享全局变量线程的传参线程的资源抢占

    多任务

    多任务介绍

    对于人来说,一边听歌,一边跳舞就是多任务。 对于电脑,简单的说,同一时间执行多个程序处理数据叫做多任务

    多任务理解

    单核CPU 单核cpu在处理多任务的时候是根据时间片轮转的方式进行的,比如执行QQ1us,然后切换微信执行1us,最后是执行钉钉1us,如此循环。因为cpu的切换速度过快,导致我们认为三个软件是同时执行的

    多核cpu 并发:当cpu不能同时执行当前所有任务时,就会循环执行,是假的多任务 并行:当cpu可以同时执行当前所有任务时,是真的多任务

    多任务的实现方式

    实现多任务有三种方式:

    线程进程协程

    线程

    线程介绍

    线程是指在一个单独进程中,对于CPU和内存而言的多个工作单位,所有线程在进程中的资源都是共享的,包括全局数据、执行代码等。

    线程的使用

    先介绍三个方法 setDaemon(True): 主线程A中,创建了子线程B,并且在主线程A中调用了B.setDaemon(),这个的意思是,把主线程A设置为守护线程,这时候,要是主线程A执行结束了,就不管子线程B是否完成,一并和主线程A退出.join(): 主线程A中,创建了子线程B,并且在主线程A中调用了B.join(),那么,主线程A会在调用的地方等待,直到子线程B完成操作后,才可以接着往下执行enumerate(): 查看线程数量

    使用

    代码示例import threading import datetime def A(): print('函数A') print(datetime.datetime.now()) def B(): print('函数B') print(datetime.datetime.now()) if __name__ == '__main__': # 指定线程到A()和B()函数里执行 t1 = threading.Thread(target=A) t2 = threading.Thread(target=B) # 执行线程 t1.start() t2.start() print('--end--')

    从输出结果可以知道,两个线程是在同一时间一起执行的。不过因为抢占式的特点,最后一条语句print('--end--')有时会在子线程的前面执行。

    join()方法的使用

    如果我们想让print('--end--')在最后执行,可以用到join()方法,当子线程结束后,主线程才会结束。

    join方法的使用,代码示例 import threading import datetime def A(): print('函数A') print(datetime.datetime.now()) def B(): print('函数B') print(datetime.datetime.now()) if __name__ == '__main__': # 指定线程到A()和B()函数里执行 t1 = threading.Thread(target=A) t2 = threading.Thread(target=B) # 执行线程 t1.start() t2.start() t1.join() t2.join() print('--end--')

    setDaemon()方法的使用

    如果不想让主线程等待子线程完成后才结束,可以使用setDaemon

    代码示例import threading import time def A(): for i in range(3): print("A") time.sleep(1) if __name__ == '__main__': t1 = threading.Thread(target=A) t1.setDaemon(True) # 要放在线程开始之前 t1.start()

    enumerate()的使用,查看线程数量

    代码示例import threading import datetime def A(): print('函数A') print(datetime.datetime.now()) def B(): print('函数B') print(datetime.datetime.now()) if __name__ == '__main__': # 创建两个主线程,指定线程到A()和B()函数里执行 t1 = threading.Thread(target=A) t2 = threading.Thread(target=B) # 执行线程 t1.start() t2.start() print(threading.enumerate()) print('--end--')

    子线程的创建与执行

    当我们调用start()方法时,子线程才会被创建,并且执行

    继承Thread类创建线程

    我们可以通过修改Thread类的run()方法里的代码,来完成重写run()方法

    代码示例import threading class T(threading.Thread): def run(self): self.a() def a(self): for i in range(3): print('a') if __name__ == '__main__': t1 = T() t1.start() # 当调用start()方法时,会主动调用run()方法

    当我们调用start()方法时,会主动调用run()方法

    多线程共享全局变量

    代码示例import threading def a(): global num num += 1 print(f'a:{num}') def b(): print(f'b:{num}') if __name__ == '__main__': num = 10 print(num) t1 = threading.Thread(target=a) t2 = threading.Thread(target=b) t1.start() t2.start() print(num)

    线程的传参

    当用线程去函数里执行代码时,我们可以看到函数后边是没有括号()的,所以涉及到传参的时候我们该怎么解决这个问题?

    解决方法 我们可以使用args参数进行传参,参数为元组当我们想要传入字典时,可以使用kwargs进行传入 代码示例import threading def a(x): print(x) def b(**kwargs): print(kwargs) if __name__ == '__main__': num = 1 # 使用args参数进行传参 t1 = threading.Thread(target=a, args=(num,)) # 使用kwargs参数进行传入字典 t2 = threading.Thread(target=b, kwargs={"A": 1}) t1.start() t2.start()

    线程的资源抢占

    代码示例import threading def a(x): global num for i in range(x): num += 1 print(f'a: {num}') def b(x): global num for i in range(x): num += 1 print(f'b: {num}') if __name__ == '__main__': num = 100 t1 = threading.Thread(target=a, args=(1000000, )) t2 = threading.Thread(target=b, args=(1000000, )) t1.start() t2.start() print(num)

    运行结果 正常的结果应该是2000100,但是因为资源抢占导致数据不正确,使用锁就可以避免这个问题,下篇博客我会细讲怎么解决这个问题。

    最后,有喜欢博主写的内容的伙伴可以点赞收藏加关注哦!

    Processed: 0.012, SQL: 9