t.join(),等待当前线程的任务执行完毕后再向下继续执行。
import threading number = 0 def _add(): global number for i in range(10000000): number += 1 t = threading.Thread(target=_add) t.start() t.join() # 主线程等待中... print(number) import threading number = 0 def _add(): global number for i in range(10000000): number += 1 def _sub(): global number for i in range(10000000): number -= 1 t1 = threading.Thread(target=_add) t2 = threading.Thread(target=_sub) t1.start() t1.join() # t1线程执行完毕,才继续往后走 t2.start() t2.join() # t2线程执行完毕,才继续往后走 print(number) import threading loop = 10000000 number = 0 def _add(count): global number for i in range(count): number += 1 def _sub(count): global number for i in range(count): number -= 1 t1 = threading.Thread(target=_add, args=(loop,)) t2 = threading.Thread(target=_sub, args=(loop,)) t1.start() t2.start() t1.join() # t1线程执行完毕,才继续往后走 t2.join() # t2线程执行完毕,才继续往后走 print(number) 2.1 守护线程
t.setDaemon(布尔值) ,守护线程(必须放在start之前)
t.setDaemon(True),设置为守护线程,主线程执行完毕后,子线程也自动关闭。
t.setDaemon(False),设置为非守护线程,主线程等待子线程,子线程执行完毕后,主线程才结束。(默认)
import threading import time def task(arg): time.sleep(5) print(\'任务\') t = threading.Thread(target=task, args=(11,)) t.setDaemon(True) # True/False \'\'\' 当设置为 True 的时候,主线程不会等待子线程的结束,继续向下执行,结束后会直接结束子线程。 设置为 False 的时候,主线程会等待子线程执行完毕,才继续向下执行。 \'\'\' t.start() print(\'END\')
线程名称的设置和获取
import threading def task(arg): # 获取当前执行此代码的线程 name = threading.current_thread().getName() print(name) # 创建10个线程。 for i in range(10): t = threading.Thread(target=task, args=(11,)) t.setName(\'日魔-{}\'.format(i))# 设置线程的名字 t.start()# 将线程设置为待调度状态
自定义线程类,直接将线程需要做的事写到run方法中。
import threading class MyThread(threading.Thread): def run(self): print(\'执行此线程\', self._args) t = MyThread(args=(100,)) t.start() import requests import threading class DouYinThread(threading.Thread): def run(self): file_name, video_url = self._args res = requests.get(video_url) with open(file_name, mode=\'wb\') as f: f.write(res.content) url_list = [ ("东北F4模仿秀.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0300f570000bvbmace0gvch7lo53oog"), ("卡特扣篮.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f3e0000bv52fpn5t6p007e34q1g"), ("罗斯mvp.mp4", "https://aweme.snssdk.com/aweme/v1/playwm/?video_id=v0200f240000buuer5aa4tij4gv6ajqg") ] for item in url_list: t = DouYinThread(args=(item[0], item[1])) t.start() 3.线程安全一个进程中可以有多个线程,且线程共享所有进程中的资源。
多个线程同时去操作一个"东西",可能会存在数据混乱的情况,例如:
示例1: 某个数加减 10000000 次
import threading loop = 10000000 number = 0 def _add(count): global number for i in range(count): number += 1 def _sub(count): global number for i in range(count): number -= 1 t1 = threading.Thread(target=_add, args=(loop,)) t2 = threading.Thread(target=_sub, args=(loop,)) t1.start() t2.start() t1.join() # t1线程执行完毕,才继续往后走 t2.join() # t2线程执行完毕,才继续往后走 print(number) # 2755 出现线程安全问题,结果不唯一 import threading lock_object = threading.RLock()# 设置锁对象。 loop = 10000000 number = 0 def _add(count): lock_object.acquire() # 加锁 global number # 使用global 声名全局变量 for i in range(count): number += 1 lock_object.release() # 释放锁 def _sub(count): lock_object.acquire() # 申请锁(等待) global number for i in range(count): number -= 1 lock_object.release() # 释放锁 # 注意:两个方法应该使用同一把锁。使用不同的锁达不到效果, t1 = threading.Thread(target=_add, args=(loop,)) t2 = threading.Thread(target=_sub, args=(loop,)) t1.start() t2.start() t1.join() # t1线程执行完毕,才继续往后走 t2.join() # t2线程执行完毕,才继续往后走 print(number) # 0
示例2:
import threading num = 0 def task(): global num for i in range(1000000): num += 1 print(num) for i in range(2): t = threading.Thread(target=task) t.start() import threading num = 0 lock_object = threading.RLock() def task(): print("开始") lock_object.acquire() # 第1个抵达的线程进入并上锁,其他线程就需要再此等待。 global num for i in range(1000000): num += 1 lock_object.release() # 线程出去,并解开锁,其他线程就可以进入并执行了 print(num) for i in range(2): t = threading.Thread(target=task) t.start() import threading num = 0 lock_object = threading.RLock() def task(): print("开始") with lock_object: # 基于上下文管理,内部自动执行 acquire 和 release global num for i in range(1000000): num += 1 print(num) for i in range(2): t = threading.Thread(target=task) t.start()注意: