1 # 线程
2 # 1.Thread
3 import threading
4 def func(a,b):
5 pass
6 t1 = threading.Thread(target=func, args=(1,2,))
7 t1.start()
8 # 2.继承
9 class MyThread(threading.Thread):
10 def run(self, a,b):
11 pass
12 t1 = MyThread(args=(1,2,))
13 t1.start()
14 # 进程
15 import multiprocess
16 def func(a,b):
17 pass
18 t1 = multiprocess.Process(target=func, args=(1,2,))
19 t1.start()
20
21 # 进程和线程区别:
22 # 1.进程是包含线程,也就是线程是在进程中创建了,一个进程可以创建多个线程。进程在创建的时候会默认创建一个进程,该进程称之为主线程,我们的代码都是由主线程开始的,所以我们在主线程中创建的线程都称之为子线程。
23 # 2.CPU调度是以进程为单位的,每个进程都是有GIL锁存在的。GIL锁的功能是保证CPU调度同一时刻只有一个现在被CPU调用。
24 # 3.因为GIL的存在掉,所以并行处理我们到底应该采用多线程还是多进程,它的标准就是你的程序需要CPU计算的强度来决定。如果你的程序是用来公式计算、数据分析就选多进程,如果你的程序偏I/O或者网络传输你就选线程,或者多进程和多线程配合使用。
25
26 # 线程方法
27 t1.join() # 主线程创建并t1.start()后,主线程调用t1.join()后就会阻塞等待t1线程执行完
28 t1.setDeamon(False) # 主线程中调用,是否等待子线程执行完。和t1.join()一个意思,区别是:setDeamon必须在start之前执行,并且是在主线程结束的时候去检查子线程是否结束
29 t1.setName(str) # 设置线程的名字,也是在start前设置
30 threading.current_thread().getName() # 获取当前线程的名字
31
32 # 线程锁
33 import threading
34 lock_obj = threading.RLock() # threading.Lock() 他们的区别是RLock嵌套锁
35 data = [1,2,3,4]
36 def func(a,b):
37 lock_obj.acquire() # 申请锁,没申请到就等待
38 lock_obj.acquire() # RLock嵌套锁才可以重复申请锁
39 data # 中间访问的数据就是被锁住的数据
40 lock_obj.release()
41 lock_obj.release() # 释放锁,别的线程才可以使用
42 t1 = threading.Thread(target=func, args=(1,2,))
43 t1.start()
44 # 线程安全:在python中一些数据类型里有些函数是自动带有线程锁的,比如:
45 list.append(x)
46 list.extend(1,2)
47 x = list[i]
48 list.sort()
49 x = y
50 x.field = y
51 dict[key] = xx
52 dict.update(d1)
53 dict.keys()
54
55 # 线程池:
56 # 线程多到一定程度并不会提高工作效率,反而会有影响
57 # 线程池就是用来限制同一时间最多有多少个线程在运行
58 # 如果你的线程池子设置最多同时执行10个线程,而往线程池中推送一百个任务的话,那么线程池子就会排队去执行它,保证同一时间最多只有10个线程运行
59 import time
60 import random
61 from concurrent.futures import ThreadPoolExecutor, Future
62
63 def task(video_url, t):
64 print('线程开始:', video_url)
65 time.sleep(2)
66 return random.randint(1, 10)
67 def done(response):
68 print('任务执行结果', response.result())
69 def save(filename):
70 def savefile(response):
71 print('闭包的方式将函数名传过来了', filename)
72 return savefile
73 pool = ThreadPoolExecutor(10) # 创建线程池,最多同时开启10个线程
74 url_list = ['www.xxxx-().com'.format(i) for i in range(15)]
75 for url in url_list:
76 future = pool.submit(task, url, 'filename') # 提交一个任务,第一个参数就是任务的函数名,后面跟的是函数的参数
77 future.add_done_callback(done) # 当任务执行完了之后,会将执行结果当做参数船给done函数执行
78 # future.add_done_callback(save('filename')) 也可以利用闭包的方式将文件名参数提前传到函数中去
79 pool.shutdown(True) # 相当于线程中的join
80
81 # 多线程单例模式
82 import threading
83 import time
84
85 class Singleton(threading.Thread):
86 instance = None
87 lock = threading.RLock()
88
89 def __init__(self, name):
90 threading.Thread.__init__(self)
91 self.name = name
92 def __new__(cls, *args, **kwargs):
93 if cls.instance:
94 return cls.instance
95 with cls.lock: # 自动枷锁解锁。如果不枷锁的话,当多个线程同时创建单例的时候很有可能会创建多个
96 if cls.instance:
97 return cls.instance
98 cls.instance = object.__new__(cls)
99 time.sleep(0.1)
100 return cls.instance