python网络编程:Queue的使用、队列阻塞、多线程、死锁

时间:2024-04-12 18:35:12

第一、Queue的使用

创建 queue队列对象
参数 :maxsize是队列中允许的最大项数。如果省略此参数,则无大小限制。
返回值q 是队列对象
具体使用程序如下:
步骤1:导入模块

from multiprocessing import Queue

步骤2:创建一个队列

q = Queue(3)#可接一个整数,表示队列的容量,如果省略则表示不设上限。
print(q.empty())#True

步骤3:往队列添加消息
格式:put(obj, block=True, timeout=None)
obj:消息对象

q.put('消息1')
print(q.empty())#False
print('~~~~~~~~~~q.qsize:',q.qsize())#1
q.put('消息2')
print(q.full())#False
q.put('消息3')

判断队列状态的方法

q.full()#判断队列是否满足,返回一个布尔值,表示当前队列是否满了。
print(q.full())#True
q.empty()#判断队列是否为空,返回一个布尔值,表示当前队列是否为空
q.qsize()#返回一个数值,表示当前队列的消息数量

步骤4:从队列中取消息

value = q.get()
print(value)#消息1
value = q.get()
print(value)#消息2
value = q.get()
print(value)#消息2

print(q.empty())#True

二、判断队列阻塞的方法

1.Queue的使用
步骤1:导入模块

from multiprocessing import Queue

步骤2:创建一个队列

q = Queue(3)#可接一个整数,表示队列的容量,如果省略则表示不设上限。
print(q.empty())#True

步骤3:往队列添加消息
格式:put(obj, block=True, timeout=None)
obj:消息对象

q.put('消息1')
print(q.empty())#False
print('~~~~~~~~~~q.qsize:',q.qsize())#1
q.put('消息2')
print(q.full())#False
q.put('消息3')

判断队列状态的方法

q.full()#判断队列是否满足,返回一个布尔值,表示当前队列是否满了。
q.empty()#判断队列是否为空,返回一个布尔值,表示当前队列是否为空
q.qsize()#返回一个数值,表示当前队列的消息数量

print(q.full())#True

步骤4:从队列中取消息

value = q.get()
print(value)#消息1
value = q.get()
print(value)#消息2
value = q.get()
print(value)#消息2
print(q.empty())#True

第三、多线程

进程是资源分配的最小单位,线程是CPU调度的最小单位(程序真正执行的时候调用的是线程),每一个进程中至少有一个线程。 
下面是线程的程序:

from urllib import request

def downloader(url):
    file_name = url.split('/')[-1]

    response = request.urlopen(url)
    content = response.read()

    with open(file_name,'wb') as fp:
        fp.write(content)
    print('子线程任务完成!')

if __name__ == '__main__':
    #主进程下面有一个主线程

    url_list = [
        'http://www.langlang2017.com/img/logo.png',
        'http://www.langlang2017.com/img/langlang1.png'
    ]
    #创建线程
    thread_list = []
    for url in url_list:
        t = Thread(target=downloader,args=(url,))
        t.start()#启动线程
        thread_list.append(t)

    for t in thread_list:
        t.join()
    print('~~~~~~主线程执行完成~~~~~~~')码片

四、 .如何统计线程数量

程序如下

from threading import Thread

import threading
import time

def sing():
    for i in range(3):
        print('唱第%d首歌'%(i))
        time.sleep(1)

def dance():
    for i in range(3):
        print('跳第%d段舞'%(i))
        time.sleep(1)

if __name__ == '__main__':
    t1 = Thread(target=sing)
    t2 = Thread(target=dance)

    t1.start()
    t2.start()

查看线程的数量, 至少得有一个主线程

  while True:
        count = len(threading.enumerate())
        print('当前线程数量:',count)
        if count <=1:
            break

五、.线程实现的第二种方法

使用继承方式开启线程,步骤如下:
1.定义一个类继承threading.Thread类。
2.复写父类的run()方法。

from threading import Thread
class MyThread(Thread):
    def __init__(self,url):
        Thread.__init__(self)
        self.url = url
        
    def run(self):
        print('线程的业务逻辑代码~')
if __name__ == '__main__':
    t = MyThread()
    t.start()

六、线程之间共享全局变量

from threading import Thread
from multiprocessing import Process
g_num =  100
def work1():
    global g_num
    for i in range(3):
        g_num+=1
    print('-----in work1,g_num is %d'%(g_num))

def work2():
    global g_num
    for i in range(3):
        g_num += 1
    print('-----in work2,g_num is %d'%(g_num))

if __name__ == '__main__':
 
    p1 = Process(target=work1)
    p1.start()

    p2 = Process(target=work2)
    p2.start()

由于多线程可以共享全局变量,所以g_num由原来的100变成了106
多进程之间内存独立,不能够共享全局变量。如果通信的话,使用Queue

七、线程非安全:共享全局变量的问题,造成的数据丢失

多线程开发的时候共享全局变量会带来资源竞争效果,也就是说线程可以对全局变量进行修改,可能会造成数据混乱。
其解决方案是加锁(互斥锁)
其步骤是:
第一:创建锁
mutex=Lock()

第二、锁定
mutex.acquire([blocking])
第三、释放
mutex.release()

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+=1
        mutex.release()#解锁

def work2():
    global g_num
    for i in range(1000000):
        mutex.acquire()#加锁
        g_num+=1
        mutex.release()#解锁

mutex = Lock()#创建锁

if __name__ == '__main__':
    # work1()
    # work2()
    # print('g_num:',g_num)#2000000

    t1 = Thread(target=work1)
    t2 = Thread(target=work2)
    t1.start()
    t2.start()

    t1.join()
    t2.join()
    print('g_num:', g_num)

锁的好处:
1.确保了某段代码只能有一个线程从头到尾完成执行。
2.阻止了多线程并发执行,包含锁的某段代码实际上是只能以单线程模式执行。
3.由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对对方的持有的锁时,可能会造成死锁

死锁

在多个线程共享资源的时候,如果两个线程分别占有一部分资源,并且同时等待对方的资源,就会造成死锁现象。

如果锁之间相互嵌套,就有可能出现死锁。因此尽量不要出现锁之间的嵌套。
python网络编程:Queue的使用、队列阻塞、多线程、死锁