#q.empty()和q.full()的使用
from multiprocessing import Queue
q=Queue(3) #设置长度为3的一个队列
print(q.empty()) #判断队列是否为空,当然,这个时候是空的
q.put(3) #往队列里加元素
q.put(4)
q.put(5)
# print(q.get_nowait()) #立即获取队列中先放进的元素(先进先出原则)
# print(q.get_nowait())
# print(q.get_nowait())
print(q.full()) #判断队列是否为满,以True和False的方式返回
print(q.empty())
value=q.get()
print(value)
q.put()和q.get()的使用
队列的阻塞问题
from multiprocessing import Queue
q=Queue(3)
q.put(1)
q.put(2)
q.put(3)
print(q.get()) #结果为1 取出先放进去的值
# q.put(4) #由于不能再往队列里填东西,所以会阻塞在这里,因而print("我在这里")这句话不会执行
print("我在这里")
from multiprocessing import Queue
q=Queue(3)
q.put(1)
q.put(2)
q.put(3)
q.put(4) #会报queue.Full错误因为队列已经满了,不能再往里增加值了
q.put()的使用以及q.qsize()的使用
from multiprocessing import Queue
q=Queue(3)
q.put(1)
q.put(2)
q.put(3)
try:
q.put(4,block=False)
except:
print("程序出现异常")
print("队列的长度为",q.qsize()) #队列的长度为 3,q.qsize()可以表示队列的长度
结果为“程序出现异常”,因为q.put(4,block=False)处于非阻塞状态,但是q队列已满,所以不能再往里加东西会报异常
put_nowait(5)的使用
from multiprocessing import Queue
q=Queue(2)
q.put(1)
q.put(2)
q.put_nowait(3) #这样会报错,q.put_nowait(3) 和q.put(3,block=False)的使用方法有相似之处都是立即执行
q.get_nowait()的使用
q.get_nowait() #等价于q.get(block=False),都是立即执行的意思
from multiprocessing import Queue
q=Queue(2)
q.put_nowait(1)
q.put_nowait(2)
print(q.get_nowait())
print(q.get_nowait())
结果分别为1和2
from multiprocessing import Process,Queue
import time,random
def write(q):
for i in ["A","B","C","D","EXIT"]:
q.put(i)
print("将%s放入队列"%(i))
time.sleep(random.random()*3)
def read(q):
while True:
if not q.empty():
value=q.get()
if value=="EXIT":
break
else:
print("从队列中得到%s"%(value))
if __name__ == '__main__':
q=Queue()
pw=Process(target=write,args=(q,))
pr=Process(target=read,args=(q,))
pw.start()
pw.join()
pr.start()
pr.join()
print("程序pw结束")
"""
将A放入队列
将B放入队列
将C放入队列
将D放入队列
将EXIT放入队列
从队列中得到A
从队列中得到B
从队列中得到C
从队列中得到D
程序pw结束
"""
线程的一些使用实例
from threading import Thread
import time,random
def doweloader(name):
for i in range(5):
print("线程%s------第%d次运行"%(name,i))
time.sleep(random.random()*2)
print("子线程%s任务结束"%(name))
if __name__ == '__main__':
name_list=["王山","王海"]
t_list=[]
for name in name_list:
t=Thread(target=doweloader,args=(name,))
t.start()
t_list.append(t)
print("父线程任务结束") #没有阻塞的话父进程父很开结束,而不是最后再结束
"""
线程王山------第0次运行
父线程任务结束
线程王海------第0次运行
父线程任务结束
线程王海------第1次运行
线程王山------第1次运行
线程王山------第2次运行
线程王海------第2次运行
线程王山------第3次运行
线程王山------第4次运行
子线程王山任务结束
线程王海------第3次运行
线程王海------第4次运行
子线程王海任务结束
"""
from threading import Thread
import time,random
def doweloader(name):
for i in range(10):
print("线程%s------第%d次运行"%(name,i))
time.sleep(random.random()*2)
print("子线程%s任务结束"%(name))
if __name__ == '__main__':
name_list=["王山","王海"]
t_list=[]
for name in name_list:
t=Thread(target=doweloader,args=(name,))
t.start()
t_list.append(t)
# for t in t_list:
# t.join()
print("父线程任务结束")
"""
线程王山------第0次运行
线程王海------第0次运行
线程王山------第1次运行
线程王山------第2次运行
线程王海------第1次运行
子线程王山任务结束
线程王海------第2次运行
子线程王海任务结束
父线程任务结束
"""
运用线程实现图片的下载
from threading import Thread
from urllib import request
def download(url):
response=request.urlopen(url)
f_name=url.split("/")[-1]
content=response.read()
with open(f_name,"wb") as fp:
fp.write(content)
if __name__ == '__main__':
url_list = ["http://img.netbian.com/file/2019/0225/smallb3d6dc1c417882c140c2190ae1c321c31551062630.jpg",
"http://img.netbian.com/file/2019/0311/small91c78151d9fe112e49d322fab157abd11552278397.jpg",
]
for url in url_list:
t=Thread(target=download,args=(url,))
t.start()
threading.enumerate()方法的使用,#threading.enumerate()可以查看当前运行的线程个数
import time,random
from threading import Thread
import threading
def sing():
for i in range(3):
print("唱第%d首歌"%(i))
time.sleep(random.random()*2)
def dance():
for i in range(3):
print("跳第%d支舞"%(i))
time.sleep(random.random())
if __name__ == '__main__':
ts=Thread(target=sing)
td=Thread(target=dance)
ts.start()
td.start()
while True:
count=len(threading.enumerate())
print("还剩%d个线程"%count)
if count==1:
break
time.sleep(2) #如果不加休眠的话由于while True运行过快,显示不出进程中执行的操作,只会显示当前还有几个进程
"""
唱第0首歌
唱第1首歌
唱第2首歌
跳第0支舞
还剩3个线程
跳第1支舞
跳第2支舞
还剩1个线程
"""
线程实现的第二种方式之重写线程
from threading import Thread
class MyThead(Thread):
def __init__(self,url):
Thread.__init__(self)
self.url=url
def run(self):
print("重写后的关键运行代码将会放在这里")
if __name__ == '__main__':
url="http://img.netbian.com/file/2019/0311/small91c78151d9fe112e49d322fab157abd11552278397.jpg",
mt=MyThead(url)
mt.run()
线程与进程之间的资源共享问题
from threading import Thread
g_num=100
def work1():
global g_num
for i in range(3):
g_num += 1
print("WORK1 g_num is %d"%(g_num))
def work2():
global g_num
for i in range(3):
g_num+=1
print("WORK2 g_nun is %d"%(g_num))
if __name__ == '__main__':
t1=Thread(target=work1)
t2=Thread(target=work2)
t1.start()
t2.start()
由于线程之间进行资源共享,所以两个线程都会对全局变量进行修改,所以会出现下面的情况
"""
WORK1 g_num is 103
WORK2 g_nun is 106
"""
from multiprocessing import Process
g_num=100
def work1():
global g_num
for i in range(3):
g_num+=1
print("WORK1 g_num is %d"%(g_num))
def work2():
global g_num
for i in range(3):
g_num+=1
print("WORK2 g_num is %d"%(g_num))
if __name__ == '__main__':
w1=Process(target=work1)
w2=Process(target=work2)
w1.start()
w2.start()
因为进程有自己独立的内存空间,两个进程之间互不干扰,所以结果如下,当然如果进程之间进行通信的话可以使用队列(Queue)
"""
WORK1 g_num is 103
WORK2 g_num is 103
"""
多线程共享全局变量引起的问题
优点:线程之间的数据交互变的简单
缺点:线程可以对全局变量进行修改,可能会造成数据混乱,即线程是非安全的
from threading import Thread
g_num=0
def work1():
global g_num
for i in range(1000000):
g_num+=1
print("Work1 g_num is %d"%(g_num))
def work2():
global g_num
for i in range(1000000):
g_num+=1
print("Work2 g_num is %d"%(g_num))
if __name__ == '__main__':
t1=Thread(target=work1)
t2=Thread(target=work2)
t1.start()
t2.start()
"""
Work1 g_num is 1000000
Work2 g_num is 1401101
"""
from threading import Thread
from threading import Lock
g_num=0 #全局变量
def work1():
global g_num
for i in range(1000000):
mutex.acquire() #加锁
g_num=g_num+1 #对g_num进行加锁和解锁
mutex.release() #解锁
print("In work1 gnu_m is %d"%(g_num))
def work2():
global g_num
for i in range(1000000):
mutex.acquire()
g_num = g_num + 1
mutex.release()
print("In work2 gnu_m is %d"%(g_num))
mutex=Lock()
if __name__ == '__main__':
# work1()
# work2()
# print(g_num) #2000000
t1=Thread(target=work1)
t1.start()
t2=Thread(target=work2)
t2.start()
t1.join()
t2.join()
print(g_num) #因为加锁了所以结果为2000000