码迷,mamicode.com
首页 > 编程语言 > 详细

并发编程之多线程篇之四

时间:2018-05-12 22:27:49      阅读:213      评论:0      收藏:0      [点我收藏+]

标签:任务   while   adp   submit   inpu   with   下一步   主线程   input   

主要内容:

  一、信号量

  二、Event事件

  三、定时器

  四、线程queue

  五、进程池与线程池

  

1?? 信号量

  1、信号量的理解

    信号量也是一把锁,可以指定信号量为5,对比互斥锁同一时间只能有一个任务抢到锁去执行,信号量同一时间可以有5个任务拿到锁去执行。

    例如:把互斥锁比作是合租房屋的人去抢一个厕所,那么信号量就是一群路人争抢公共厕所,公共厕所有多个坑位,这意味同一时间可以有多个人争抢公共厕所,公共厕所有多个坑位,这意味着同一时间可以有多个人上公共厕所,但公共厕所容纳的人数是一定的,这便是信号量的大小。

  2、实例:

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
from threading import Thread,Semaphore,currentThread
import time,random
# Semaphore 指信号量,本质也是互斥锁,不同在于可以同时生成多把锁,把Lock比作私单人卫生间的话,一次只允许一个人使用;那么Semaphere就是公共厕所,一次允许指定的人数同时使用

sm = Semaphore(4) # 生成了五把锁
def task():
    # sm.acquire()
    # print(‘%s is in wc‘%currentThread().getName())
    # sm.acquire()
    with sm:
        time.sleep(random.randint(1, 3))
        print(%s is in%currentThread().getName())

if __name__ == __main__:
    for i in range(10):
        t = Thread(target=task)
        t.start()

 

2?? Event事件

  1、Event对象的理解:

    线程的一个关键特性是每个线程都是独立运行且状态不可预测。如果程序中的其 他线程需要通过判断

  某个线程的状态来确定自己下一步的操作,这时线程同步问题就会变得非常棘手。为了解决这些问题,我们需要

  使用threading库中的Event对象。 

     对象包含一个可由线程设置的信号标志,它允许线程等待某些事件的发生。在初始情况下,Event对象中的

  信号标志被设置为假。如果有线程等待一个Event对象, 而这个Event对象的标志为假,那么这个线程将会被一直

  阻塞直至该标志为真。一个线程如果将一个Event对象的信号标志设置为真,它将唤醒所有等待这个Event对象的线程。

  如果一个线程等待一个已经被设置为真的Event对象,那么它将忽略这个事件, 继续执行。

  2、参数介绍:

from threading import Event

event.isSet():返回event的状态值;

event.wait():如果 event.isSet()==False将阻塞线程;

event.set(): 设置event的状态值为True,所有阻塞池的线程激活进入就绪状态, 等待操作系统调度;

event.clear():恢复event的状态值为False。

  3、实例1:   

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong

from threading import Thread,Event,currentThread
import time

event = Event()
def student(name):
    print(学生%s在听课%name)
    event.wait() # 等待event.set()运行才能释放,接着运行
    print(学生%s下课了%name)

def teacher(name):
    print(老师%s在上课%name)
    time.sleep(8)
    event.set() # 释放event.wait(),继续执行
if __name__ == __main__:
    s1 = Thread(target=student,args=(cc1,))
    s2 = Thread(target=student,args=(cc2,))
    s3 = Thread(target=student,args=(cc3,))
    t1 = Thread(target=teacher,args=(CC,))

    s1.start()
    s2.start()
    s3.start()
    t1.start()
   
‘‘‘
学生cc1在听课
学生cc2在听课
学生cc3在听课
老师CC在上课
学生cc2下课了
学生cc1下课了
学生cc3下课了
‘‘‘ 

  实例2:

技术分享图片
from threading import Thread,Event,currentThread
import time

event = Event()
def client():
    n = 0
    while not event.is_set(): # is_set() 是否激活线程
        if n == 3:
            print(time out,%s connected failed%currentThread().getName())
            return
        print(%s try %s%(currentThread().getName(),n))
        event.wait(0.5)
        n += 1
    print(%s is connected%currentThread().getName())

def check():
    print(%s is checking%currentThread().getName())
    time.sleep(5)
    event.set()
if __name__ == __main__:
    for i in range(3):
        t = Thread(target=client)
        t.start()
    t = Thread(target=check)
    t.start()
‘‘‘
Thread-1 try 0
Thread-2 try 0
Thread-3 try 0
Thread-4 is checking
Thread-3 try 1
Thread-1 try 1
Thread-2 try 1
Thread-2 try 2参数
Thread-1 try 2
Thread-3 try 2
time out,Thread-2 connected failed
time out,Thread-1 connected failed
time out,Thread-3 connected failed
‘‘‘
View Code

 

3?? 定时器

1、定时器的理解:

  定时器,即指定n秒后执行某操作。

2、实例1:

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong

from threading import Thread,Timer
import random
def task(name):
    print(hello %s,welcome login!%name) # hello hyt,welcome login!
time = Timer(3,task,args=(hyt,)) # 等待指定时间,执行线程
time.start()

实例2--自动更新验证码

技术分享图片
#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong

from threading import Thread,Timer
import random

class Check_number:
    def __init__(self):
        self.cash_code() # 程序一开始便实例化一个验证码
    def make_code(self,n=4):
        res = ‘‘
        for i in range(n):
            s1 = str(random.randint(0,9)) # 0到9间的任意自然数
            s2 = chr(random.randint(65,90)) # 24个小写字母
            res += random.choice([s1,s2]) # 字符和数字的任意组合
        return res
    def cash_code(self,interval=3):
        self.code = self.make_code()  # 实例化一个验证码
        print(self.code) # 打印验证码
        self.t = Timer(interval,self.make_code) # 定时器,等待指定时间再运行
        self.t.start()

    def check(self):
        while True:
            mes = input(输入验证码>>>:).strip()
            if self.code == mes.upper():
                print(输入正确!)
                self.t.cancel() # 关闭定时器
                break

obj = Check_number()
obj.check()
View Code

4?? 线程queue

 1、queue  队列,先进先出

 2、实例: 

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
import queue
# 队列,先进先出
q = queue.Queue(3) # 括号内指定队列长度
q.put(one)
q.put(2)
q.put(third)
q.put(4) # 此时队列已满,无法再放数据,造成堵塞,不会提示队列是否已满
q.put(4,block=True,timeout=5) # 与上式完全相同,但会提示队列已满,block表示阻塞,后面的timeout表示等待,延时指定时间报错
q.get_nowait(4)  # 表示不等待,直接提示已满
q.put(4,block=False) # 不阻塞,直接提示,与上式相同

print(q.get()) # one
print(q.get()) # 2
print(q.get()) # third
print(q.get()) # 没有任何数据,且不提示
print(q.get_nowait()) # 不阻塞,直接报错提示队列已取空
print(q.get(block=True,timeout=3)) # 阻塞等待3秒,再报错提示

# 堆栈,后进先出,用法和队列相同
q2 = queue.LifoQueue(3) # 后进先出
q2.put(one)
q2.put(two)
q2.put(3)

print(q2.get())
print(q2.get())
print(q2.get())

# 优先级队列
q3 = queue.PriorityQueue(3)
q3.put((10,1))
q3.put((6,2))
q3.put((20,3))
print(q3.get())
print(q3.get())
print(q3.get())
‘‘‘数字越小优先级越高
(6, 2)
(10, 1)
(20, 3)
‘‘‘

5?? 进程池与线程池

  1、进程池 

#!/usr/bin/env python3
#-*- coding:utf-8 -*-
# write by congcong
from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
import random,os,time

# 进程池
def task(name):
    print(name:%s pid:%s run %(name,os.getpid()))
    time.sleep(random.randint(1,5))

if __name__ == __main__:
    pool = ProcessPoolExecutor(3) # 不指定数目时,默认指定CPU核心数,此处进程池同时接收3个进程,且从始至终只有三个进程在运行(控制进程数)
    for i in range(5):
        pool.submit(task,cc%s%i) # 异步提交,不需要等待,提交了就接着提交下一波
    pool.shutdown(wait=True) # 关闭进程池的入口,进程池内进程未执行完之前(进程池内的计数器每执行完一个进程,自减1,直到减为0)不允许其他进程进入进程池
    print(主进程)
‘‘‘未加pool.shutdown()-->wait=True是默认参数
主进程
name:cc0 pid:2656 run 
name:cc1 pid:7316 run 
name:cc2 pid:4404 run 
name:cc3 pid:7316 run 
name:cc4 pid:2656 run 
‘‘‘
‘‘‘加pool.shutdown(wait=True)之后输出,保证了进程的安全性
name:cc0 pid:1536 run 
name:cc1 pid:7316 run 
name:cc2 pid:1900 run 
name:cc3 pid:7316 run 
name:cc4 pid:1536 run 
主进程

‘‘‘

  2、线程池

from threading import Thread,currentThread
# 线程池
def task():
    print(name:%s pid:%s is running%(currentThread().getName(),os.getpid()))
    time.sleep(random.randint(1,3))

if __name__ == __main__:
    pool = ThreadPoolExecutor(3) # 与进程池同理,此时同时可容纳3个线程,自始至终就3个线程在运行(控制线程数)
    for i in range(5):
        pool.submit(task) # 异步提交,不管是否成功,继续提交下一个
    pool.shutdown() # 关闭线程池入口
    print(主线程)
‘‘‘
name:ThreadPoolExecutor-0_0 pid:772 is running
name:ThreadPoolExecutor-0_1 pid:772 is running
name:ThreadPoolExecutor-0_2 pid:772 is running
name:ThreadPoolExecutor-0_2 pid:772 is running
name:ThreadPoolExecutor-0_0 pid:772 is running
主线程
‘‘‘

 

  

  

并发编程之多线程篇之四

标签:任务   while   adp   submit   inpu   with   下一步   主线程   input   

原文地址:https://www.cnblogs.com/schut/p/9030051.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!