import _thread # 多线程
import win32api
def show(i):
mystr = win32api.MessageBox(0,"你真帅","来自Joker的问候",0)
for i in range(5):
_thread.start_new_thread(show,(i,
while True:
pass
(1)import _thread # 多线程
(2)for i in range(5): # 这是小弟线程
_thread.start_new_thread(show,(i,)) # 前面是执行函数,后面是一个元组,可以不写前提是函数没有形参
(3)def show(i):
# 0 代表系统,你真帅代表内容,来自JOKER代表标题,0代表窗口类型0,1,2,3
(4)while True: # 在这里加入死循环是为了脚本主线程不死,小弟线程才能运行
import _thread
import time
def go():
for i in range(5):
print(i,"-------")
time.sleep(1)
for i in range(5): # 同时执行5次
_thread.start_new_thread(go,())
for j in range(6): # 让主线程卡顿6秒
time.sleep(1)
print("over")
结果显示:
0 -------
0 -------
0 -------
0 -------
0 -------
1 -------
1 -------
1 -------
1 -------
1 -------
2 -------
2 -------
2 -------
2 -------
2 -------
3 -------
3 -------
3 -------
3 -------
3 -------
4 -------
4 -------
4 -------
4 -------
4 -------
over
import _thread
num = 0
def add():
for _ in range(1000000):
global num
num += 1
print(num)
'''
for j in range(5):
add()
'''
for i in range(5):
_thread.start_new_thread(add,())
# 这里就是线程冲突,5个线程同时抢夺num的资源,导致最后结果错误
'''
1144840
1488805
1671079
1700819
1920182
'''
while True: # 防止主线程不死
pass
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def run(self): # 重写threading.Thread类中的run函数
win32api.MessageBox(0,"hello",'joker',0)
for i in range(5): # 同时创建5个线程
t = Mythread() # 初始化
t.start() # 开启
while True:
pass
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def run(self): # 定义函数
win32api.MessageBox(0,"hello",'joker',0)
for i in range(5):
t = Mythread() # 初始化
t.start() # 开启
t.join()
print("game over")
结果显示:
(1) 等待一个线程执行完毕,再执行下一个线程,一方面可以阻止脚本主线程死掉,另一方面也可以防止线程冲突的一种办法。
(2)t.join() 如果将其放在外部的不确定因素是,系统给for 循环和下面的代码锁定了一片内存,当循环执行完成之后。
(3)内存就开锁了,但是里面的东西还依然存在,所以才结束一个窗体,game over就出来了。
(4) 就和删除文件后,内存中可能还有文件一样的道理
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def __init__(self, num):
threading.Thread.__init__(self) # 父类初始化
self.num = num
def run(self): # 定义函数
win32api.MessageBox(0, "hello" + str(self.num), 'joker', 0)
print(self.getName()) # 获取线程名
Mythd = []
for i in range(5):
t = Mythread(i) # 初始化
print(i)
t.start() # 开启
Mythd.append(t) # 将乱序线程(同时抢夺run这个函数)加入列表
for j in Mythd:
# 这里与顺序不同,上面显示所有的线程都加入Mthd列表(所以一次性跳出5个窗口,但是主线程还没死,因为有join卡住)。
# j是线程
j.join() # 这里主线程同时等待所有线程都执行完毕,才执行“game over”
print("game over")
结果显示:
0
1
2
3
4
Thread-3
Thread-2
Thread-4
Thread-1
Thread-5
game over
import threading
num = 0
mutex = threading.Lock() # 创建一个锁,threading.Lock()是一个类
class Myhtread(threading.Thread):
def run(self):
global num
if mutex.acquire(1): # 如果锁成功,那么线程继续干活,如果锁失败,下面的线程一直等待锁成功,1,代表独占
for i in range(1000): # 数字小的时候还是不会产生线程冲突的
num += 1
mutex.release() # 释放锁,一定切记
print(num)
mythread = []
for i in range(5):
t = Myhtread()
t.start()
mythread.append(t)
for thread in mythread:
thread.join() # 或者直接将thread.join()加入for i in range(5),也能解决线程冲突,但是貌似就变成单线程了
print("game over")
结果显示:
1000
2000
3000
4000
5000
game over
import threading
import time
boymutex = threading.Lock() # 创建一个锁
girlmutex = threading.Lock() # 创建一个锁
class boy(threading.Thread):
def run(self):
if boymutex.acquire(1): # 锁定成功就继续执行,锁定不成功,就一直等待
print(self.name + "boy say i am sorry up")
# time.sleep(3) # 时间过短的话也可以并发执行,不会锁死
if girlmutex.acquire(1): # 锁定不成功,因为下面已经锁定
print(self.name + "boy say i am sorry down")
girlmutex.release()
boymutex.release()
class girl(threading.Thread):
def run(self):
if girlmutex.acquire(1): # 锁定成功就继续执行,锁定不成功,就一直等待
print(self.name + "girl say i am sorry up")
# time.sleep(3)
if boymutex.acquire(1): # 锁定不成功,同理上面已经锁定一直等待
print(self.name + "girl say i am sorry down")
boymutex.release()
girlmutex.release()
# 开启两个线程
# boy1 = boy() # Thread-1boy 第一个线程
# boy1.start()
# girl1 = girl()
# girl1.start()
'''
这种例子时间过短是无法很好的产生死锁
for i in range(10):
Mythread1().start()
Mythread2().start()
'''
for i in range(1000):
boy().start()
girl().start()
结果显示:
Thread-1boy say i am sorry up
Thread-2girl say i am sorry up
import threading
num = 0
mutext = threading.RLock() # PLOCK避免单线程死锁
class Mythreading(threading.Thread):
def run(self):
global num
if mutext.acquire(1):
num += 1
print(self.name, num)
if mutext.acquire(1):
num += 1000
mutext.release()
mutext.release()
for i in range(5): # 开启5个进程
t = Mythreading()
t.start()
结果显示:
Thread-1 1
Thread-2 1002
Thread-3 2003
Thread-4 3004
Thread-5 4005
# 基于函数构造实现多线程
import threading
import win32api
def show():
win32api.MessageBox(0, "这是一个测试", "来自Joker", 0)
# target=show是线程函数,args=()是参数
threading.Thread(target=show, args=()).start()
threading.Thread(target=show, args=()).start()
第一种用函数创建多线程,但是需要处理让脚本主线程不死
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def run(self): # 定义函数
win32api.MessageBox(0, "hello", 'joker', 0)
Mythd = []
for i in range(5):
t = Mythread() # 初始化
print(i)
t.start() # 开启
Mythd.append(t) # 将乱序线程(同时抢夺run这个函数)加入列表
for j in Mythd:
# 这里与顺序不同,上面显示所有的线程都加入Mthd列表(所以一次性跳出5个窗口,但是主线程还没死,因为有join卡住)。
# j是线程
j.join() # 这里主线程同时等待所有线程都执行完毕,才执行“game over”
print("game over")
import threading
import win32api
class Mythread(threading.Thread): # 继承threading.Thread类
def run(self): # 重写threading.Thread类中的run函数
win32api.MessageBox(0,"hello",'joker',0)
for i in range(5): # 同时创建5个线程
t = Mythread() # 初始化
t.start() # 开启
while True:
pass
'''
'''
def show(i):
win32api.MessageBox(0,"这是一个测试","来自Joker",0)
threading.Thread(target=show,args=(i,)).start() # 切记这里的args是一个元组
threading.Thread(target=show,args=(i,)).start()
import threading
import time
sem = threading.Semaphore(2) # 限制最大线程数为2个
def gothread():
with sem: # 锁定数量
for i in range(10):
print(threading.current_thread().name, i) # 打印线程名字
time.sleep(1)
for i in range(5):
threading.Thread(target=gothread).start() # 乱序执行多线程,就可以考虑为有些cpu牛逼些能够执行快一点
结果显示:
Thread-1 0
Thread-2 0
Thread-2 1
Thread-1 1
Thread-2 2
Thread-1 2
Thread-1 3
Thread-2 3
Thread-2 4
Thread-1 4
Thread-1 5
Thread-2 5
Thread-1 6
Thread-2 6
Thread-1 7
Thread-2 7
Thread-2 8
Thread-1 8
Thread-1 9
Thread-2 9
import threading
bar = threading.Barrier(2)
def sever():
print(threading.current_thread().name,"start")
bar.wait()
print(threading.current_thread().name,"end")
for i in range(3):
threading.Thread(target=sever).start()
结果显示:
Thread-1 start
Thread-2 start
Thread-2 end
Thread-1 end
Thread-3 start
这里出现Thread-3 是因为锁定在"start"之后,所以最后面Thread-3 end 是无法出现的
(1)为了合理利用资源
(2)凑出线程数量,也就是说一定要至少凑成两个才能执行
(3)换而言之,也就是说只有创建线程数是2,或者2的倍数才能全部执行
import threading
import time
def goevent():
e = threading.Event() # 事件
def go():
e.wait() # 等待事件,线程卡顿,等待set消息
print("go")
threading.Thread(target=go).start() # 需要创建一个线程
return e
t = goevent()
time.sleep(3)
t.set() # 激发事件
结果显示:go
import threading
import time
def goevent():
e = threading.Event() # 事件
def go():
for i in range(10):
e.wait() # 等待事件,线程卡顿,等待set消息,只调用一次
e.clear() # 重置线程等待
print("go",i)
threading.Thread(target=go).start() # 创建一个线程
return e
t = goevent()
for i in range(5):
time.sleep(i)
t.set()
结果显示:
go 0
go 1
go 2
go 3
go 4
import threading
import time
def go1():
with cond:
for i in range(10):
time.sleep(1)
print(threading.current_thread().name, i)
if i == 5:
cond.wait() # 等待,只有在其他相同线程条件变量唤醒时才继续执行
print("hahahha")
def go2():
with cond: # 使用条件变量
for i in range(10):
time.sleep(1)
print(threading.current_thread().name, i)
cond.notify() # 通知唤醒其他线程
cond = threading.Condition() # 线程条件变量
threading.Thread(target=go1).start()
threading.Thread(target=go2).start()
(1) wait()
此方法释放底层的锁,然后阻塞,直到它通过notify()或notify_all()调用唤醒相同的条件, 在另一个线程中变量,或直到发生可选的超时。一旦唤醒或超时,它重新获得锁定并返回。
(2)notify()
在这种情况下唤醒一个或多个线程,如果有的话。 如果调用线程没有获得这个方法的锁 称为,引发了一个RuntimeError。这个方法至多唤醒n个等待条件的线程 变量; 如果没有线程正在等待,那么这是一个无操作。
(3)代码逻辑
cond只有一个,线程1线锁定cond,当线程1跑到i==5的时候
此时进入condition等待,将资源释放出来,
这时候线程2进入,一口气全部跑完i,跑到最后以cond.notifly通知
将资源再放出来,此时线程1重新锁定。
在这里插入import requests
import threading
import re
class maoyan_top500(threading.Thread):
def __init__(self, start_, end_,lock):
threading.Thread.__init__(self)
self.headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
self.base_url = 'https://maoyan.com/board/4?offset=%d'
self.start_ = start_
self.end_ = end_
self.lock = lock
def run(self):
for offset in range(self.start_, self.end_, 10):
url = self.base_url % offset
response = requests.get(url, headers=self.headers)
html = response.text
info_list = self.get_Information(html)
with self.lock:
self.write(info_list)
print('offset {} OK !'.format(offset))
def get_Information(self, html):
information_list = []
for line in html.split('\n'):
if 'class="image-link"' in line:
movie_name = line.split('title="')[1].split('"')[0]
information_list.append(movie_name)
if 'class="integer"' in line:
res = re.search(
'(\d\.)(\d)
',
line)
integer = res.group(1)
fraction = res.group(2)
score = integer + fraction
information_list.append(score)
return information_list
def write(self,info_list):
str_ = str(info_list) + '\n'
with open('C:\\Users\\admin\\Desktop\\res.txt',mode='a',encoding='utf8') as file:
file.write(str_)
if __name__ == "__main__":
threads = []
lock = threading.Lock()
for i in range(2):
t = maoyan_top500(start_=i * 50, end_=(i + 1) * 50,lock=lock)
t.start()
threads.append(t)
for t in threads:
t.join()
print('Over')代码片