进程线程资源分配以及阻塞死锁之那些事儿的总结/day18

#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
 

 

猜你喜欢

转载自blog.csdn.net/qq_39112101/article/details/88545338
今日推荐