首页 > 编程语言 > 详细

python 之 并发编程(线程Event、协程)

时间:2019-07-26 23:15:37      阅读:92      评论:0      收藏:0      [点我收藏+]

9.14 线程Event

connect线程执行到event.wait()时开始等待,直到check线程执行event.set()后立即继续线程connect

from threading import Event,current_thread,Thread
import time
event=Event()
def check():
    print(%s 正在检测服务是否正常.... %current_thread().name)
    time.sleep(3)
    event.set()
?
def connect():
    print(%s 等待连接... %current_thread().name)
    event.wait()
    print(%s 开始连接... % current_thread().name)
?
if __name__ == __main__:
    t1=Thread(target=connect)
    t2=Thread(target=connect)
    t3=Thread(target=connect)
?
    c1=Thread(target=check)
?
    t1.start()
    t2.start()
    t3.start()
    c1.start()

connect线程执行到event.wait(1)时开始等待1秒,count计数+1,如果到check线程执行event.set()前已经4秒,则终止线程connect,否则event.is_set() is True ,立即继续线程connect

技术分享图片
from threading import Event,current_thread,Thread
import time
event=Event()
def check():
    print(%s 正在检测服务是否正常.... %current_thread().name)
    time.sleep(5)
    event.set()
?
def connect():
    count=1
    while not event.is_set():   #event是否被set过,是返回True,否返回False
        if count ==  4:
            print(尝试的次数过多,请稍后重试)
            return
        print(%s 尝试第%s次连接... %(current_thread().name,count))
        event.wait(1)
        count+=1
    print(%s 开始连接... % current_thread().name)
?
if __name__ == __main__:
    t1=Thread(target=connect)
    t2=Thread(target=connect)
    t3=Thread(target=connect)
?
    c1=Thread(target=check)
?
    t1.start()
    t2.start()
    t3.start()
    c1.start()
View Code

9.15 协程

协程:是单线程下的并发,又称微线程,纤程。一句话说明什么是线程:协程是一种用户态的轻量级线程,即协程是由用户程序自己控制调度的。

  1. python的线程属于内核级别的,即由操作系统控制调度(如单线程遇到i/o或执行时间过长就会被迫交出cpu执行权限,切换其他线程运行)

  2. 单线程内开启协程,一旦遇到i/o,就会从应用程序级别(而非操作系统)控制切换到其他任务,以此来提升效率(非i/o操作的切换与效率无关)

  3. 对比操作系统控制线程的切换,用户在单线程内控制协程的切换

  优点:
1. 协程的切换开销更小,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级
2. 单线程内就可以实现并发的效果,最大限度地利用cpu
   
缺点:
1. 协程的本质是单线程下,无法利用多核,可以是一个程序开启多个进程,每个进程内开启多个线程,每个线程内开启协程
2. 协程指的是单个线程,因而一旦协程出现阻塞,将会阻塞整个线程

9.151 greenlet模块

 from greenlet import greenlet
  import time
  
  def eat(name):
      print(%s eat 1 %name)
      #time.sleep(30)           遇到i/o不能自动切换
      g2.switch(alex)
      print(%s eat 2 %name)
      g2.switch()
  def play(name):
      print(%s play 1 %name)
      g1.switch()
      print(%s play 2 %name)
  
  g1=greenlet(eat)
  g2=greenlet(play)
  
  g1.switch(egon) # egon eat 1   alex play 1   egon eat 2   alex play 2

9.152 gevent模块

import gevent
?
def eat(name):
    print(%s eat 1 %name)
    gevent.sleep(5)         #只检测gevent的i/o
    print(%s eat 2 %name)
def play(name):
    print(%s play 1 %name)
    gevent.sleep(3)
    print(%s play 2 %name)
?
g1=gevent.spawn(eat,egon) #异步提交任务
g2=gevent.spawn(play,alex)
?
# gevent.sleep(100)
# g1.join()
# g2.join()                # joinall等待任务执行完毕再结束线程
gevent.joinall([g1,g2])     # egon eat 1     alex play 1    alex play 2   egon eat 2
from gevent import monkey;monkey.patch_all()#标记所有(包括time等)的i/o
import gevent
import time
?
def eat(name):
    print(%s eat 1 %name)
    time.sleep(5)            #time的i/o也可以检测
    print(%s eat 2 %name)
def play(name):
    print(%s play 1 %name)
    time.sleep(3)
    print(%s play 2 %name)
?
g1=gevent.spawn(eat,egon)
g2=gevent.spawn(play,alex)
?
# gevent.sleep(100)
# g1.join()
# g2.join()
gevent.joinall([g1,g2])       # egon eat 1   alex play 1    alex play 2   egon eat 2

验证协程的假名:

技术分享图片
from gevent import monkey;monkey.patch_all()#标记所有time等的i/o
from threading import current_thread
import gevent
import time
?
def eat():
    print(%s eat 1 %current_thread().name)
    time.sleep(5)
    print(%s eat 2 %current_thread().name)
def play():
    print(%s play 1 %current_thread().name)
    time.sleep(3)
    print(%s play 2 %current_thread().name)
?
g1=gevent.spawn(eat)
g2=gevent.spawn(play)
?
# gevent.sleep(100)
# g1.join()
# g2.join()
print(current_thread().name)#MainThread
gevent.joinall([g1,g2])     #DummyThread-1 eat 1     DummyThread-2 play 1  DummyThread-2 play 2                             DummyThread-1 eat 2
View Code

9.153 基于协程实现并发的套接字通信

服务端:

技术分享图片
from gevent import monkey,spawn;monkey.patch_all()#标记所有time等的i/o
from threading import Thread
from socket import *
?
def talk(conn):
    while True:
        try:
            data=conn.recv(1024)
            if not data:break
            conn.send(data.upper())
        except ConnectionResetError:
            break
    conn.close()
?
def server(ip,port,backlog=5):
    s = socket()
    s.bind((ip,port))
    s.listen(backlog)
?
    while True:
        conn, addr = s.accept()
        print(addr)
      
        g=spawn(talk,conn)  # 通信
    s.close()
?
if __name__ == __main__:
    spawn(server,127.0.0.1,8080).join()
    # server((‘127.0.0.1‘,8080))
View Code

客户端:

技术分享图片
from threading import Thread,current_thread
from socket import *
import os
?
def client():
    client = socket()
    client.connect((127.0.0.1, 8080))
?
    while True:
        data = %s hello % current_thread().name
        client.send(data.encode(utf-8))
        res = client.recv(1024)
        print(res.decode(utf-8))
?
if __name__ == __main__:
    for i in range(1000):
        t=Thread(target=client)
        t.start()
View Code

python 之 并发编程(线程Event、协程)

原文:https://www.cnblogs.com/mylu/p/11253143.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!