day11 线程、进程、协程、缓存

线程

基本使用:

标准线程:

例子1:创建基本线程
import threading #导入模块
def f1(arg,args):  #创建函数
    print(arg,args)

t = threading.Thread(target=f1,args=(123,456))  #创建线程
t.start() #执行线程

自定义线程:

例子2:
import threading #导入模块
class MyThread(threading.Thread): #创建一个类MyThread继承父类(threading.Thread)
    def __init__(self,func,args): #定义__init__构造函数
        self.func = func
        self.args = args
        super(MyThread,self).__init__() #继承父类的__init__构造方法 父类的构造方法中封装了grop=None,target=None,name=None,args=(),kwargs=None,*,daeon=None

    def run(self): #定义run方法,此方法相当于是执行定义的方法f2。
        self.func(self.args)

def f2(arg): #定义一个f2方法
    print(arg)

obj = MyThread(f2,123) #创建一个对象obj,传参f2,123.
obj.start() #执行线程  

线程锁:

由于线程之间是进行随机调度,并且每个线程可能只执行n条执行之后,当多个线程同时修改同一条数据时可能会出现脏数据,所以,出现了线程锁 - 同一时刻允许一个线程执行操作。

import threading #导入线程模块
import  time #导入时间模块

NUM = 10 #定义一个全局变量

def func(l): #定义一个函数
    global NUM  #函数内使用全局变量
    l.acquire()  # 上锁
    NUM -= 1 #修改全局变量,让全局变量自减一
    time.sleep(2) #时间等待2秒
    print(NUM)
    l.release()  # 开锁

# lock = threading.Lock()
lock = threading.RLock() #加锁


for i in range(10): 
    t = threading.Thread(target=func, args=(lock, )) #创建线程
    t.start() #执行线程

# Lock只支持单层锁
# RLock支持多层锁,一般常用RLock

 队列

队列的种类活类型:

1、queue.Queue先进先出队列;2、queue.LifoQueue后进先出队列;3、queue.PriorityQueue优先级队列;4、queue.deque双向队列

队列基本参数解释:

# put放数据(默认阻塞),是否阻塞,阻塞时的超时时间

# get取数据(默认阻塞),是否阻塞,阻塞时的超时时间

# queue.Queue(n),n队列最大长度

# empty() #检查队列是否为空

# qsize() #真实个数

# maxsize()  #最大支持的个数

# join()  #队列中的任务全部完成之后(元素没有被完成(取出))

# task_done()  #结束取值任务

例子列举:

queue.Queue先进先出队列

import queue

q = queue.Queue(3)  # 定义队列,最多可放10个数据
q.put(11)  # put存放数据
q.put(22)
q.put(33,block=False, timeout=2)  # 默认block阻塞,timeout超时时间

print(q.qsize())  # 真实数据个数
print(q.empty())  #查看队列是否为空
print(q.get())
q.task_done()  #结束取值任务
print(q.get())
q.task_done()  #结束取值任务
print(q.get(block=False, timeout=2)) # 默认block阻塞,timeout超时时间
q.task_done()  #结束取值任务
print(q.empty())  #查看队列是否为空
q.join()  # 阻塞进程,当队列中任务执行完毕后不再阻塞,与task_done()配合使用

queue.LifoQueue后进先出队列

q = queue.LifoQueue()
q.put(123)
q.put(456)
q.put(789)
print(q.get())

queue.PriorityQueue优先级队列

q = queue.PriorityQueue()
q.put((1, "alex4"))
q.put((1, "alex3"))
q.put((2, "alex2"))
q.put((0, "alex0"))
q.put((1, "alex1"))
print(q.get()
print(q.get())
print(q.get())
print(q.get())

queue.deque双向队列

q = queue.deque()
q.append(123)
q.append(456)
q.appendleft(789)
print(q.pop())
print(q.popleft())  

生产消费者模型———队列:

import queue
import threading
import time

q = queue.Queue()

def productor(arg):
    """
    买票
    :param arg:
    :return:
    """
    q.put(str(arg)+ '票')

for i in range(300):
    t = threading.Thread(target=productor, args=(i, ))
    t.start()

def consumer(arg):
    """
    服务器后台
    :param arg:
    :return:
    """
    while True:
        print(arg, q.get())
        time.sleep(2)

for j in range(3):
    t = threading.Thread(target=consumer, args=(j, ))
    t.start()

事件(event):

python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

clear:将“Flag”设置为False(红灯)

set:将“Flag”设置为True(绿灯)

例子:

import threading

def func(i,e):
    print(i)
    e.wait() #检测是什么等,如果是红灯,停;绿灯,行
    print(i+100)

event = threading.Event()

for i in range(10):
    t = threading.Thread(target=func, args=(i,event,))
    t.start()


event.clear() #设置成红灯
inp = input(">>>")
if inp == "1":
    event.set() #设置成绿灯

条件(Condition)

解释:当线程满足某些条件时,才释放多个线程。

wait():

import threading
def func(i,con):
    print(i)
    con.acquire()
    con.wait()
    print(i+100)
    con.release()

c = threading.Condition()
for i in range(10):
    t = threading.Thread(target=func, args=(i,c,))
    t.start()

while True:
    inp = input('>>>')
    if inp == 'q':
        break
    c.acquire()
    c.notify(int(inp))
    c.release()

wait.for()

import threading

def condition():
    ret = False
    r = input('>>>')
    if r == 'true':
        ret = True
    else:
        ret = False
    return ret


def func(i,con):
    print(i)
    con.acquire()
    con.wait_for(condition)
    print(i+100)
    con.release()

c = threading.Condition()
for i in range(10):
    t = threading.Thread(target=func, args=(i,c,))
    t.start()

Time()

定时器,指N秒后执行某操作

from threading import Timer

def hello():
      print("hello,world")
t = Timer(1,hello) #1为等待1秒,hello为函数
t.start()

线程池:

1、一个容器(最大个数)、2、取一个少一个、3、无线程时等待、4、线程执行完毕,归还线程

初级版线程池:

 1 # 线程池
 2 import queue
 3 import threading
 4 import time
 5 class ThreadPool:
 6     def __init__(self,maxsize=5):
 7         self.maxsize = maxsize
 8         self._q = queue.Queue(maxsize)
 9         for i in range(maxsize):
10             self._q.put(threading.Thread)
11 
12     def get_thread(self):
13         return self._q.get()
14 
15     def add_thread(self):
16         self._q.put(threading.Thread)
17 
18 pool = ThreadPool(5)
19 
20 def task(arg,p):
21     print(arg)
22     time.sleep(1)
23     p.add_thread()
24 
25 for i in range(100):
26      #thrading.Thread类
27      t = pool.get_thread()
28      obj = t(target = task,args = (i,pool,))
29      obj.start()
初级版本线程池

 高级版线程池:

  1 import queue
  2 import threading
  3 import contextlib
  4 import time
  5 
  6 StopEvent = object()
  7 
  8 
  9 class ThreadPool(object):
 10 
 11     def __init__(self, max_num, max_task_num = None):
 12         if max_task_num:
 13             self.q = queue.Queue(max_task_num)
 14         else:
 15             self.q = queue.Queue()
 16         self.max_num = max_num
 17         self.cancel = False
 18         self.terminal = False
 19         self.generate_list = []
 20         self.free_list = []
 21 
 22     def run(self, func, args, callback=None):
 23         """
 24         线程池执行一个任务
 25         :param func: 任务函数
 26         :param args: 任务函数所需参数
 27         :param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
 28         :return: 如果线程池已经终止,则返回True否则None
 29         """
 30         if self.cancel:
 31             return
 32         if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
 33             self.generate_thread()
 34         w = (func, args, callback,)
 35         self.q.put(w)
 36 
 37     def generate_thread(self):
 38         """
 39         创建一个线程
 40         """
 41         t = threading.Thread(target=self.call)
 42         t.start()
 43 
 44     def call(self):
 45         """
 46         循环去获取任务函数并执行任务函数
 47         """
 48         current_thread = threading.currentThread
 49         self.generate_list.append(current_thread)
 50 
 51         event = self.q.get()
 52         while event != StopEvent:
 53 
 54             func, arguments, callback = event
 55             try:
 56                 result = func(*arguments)
 57                 success = True
 58             except Exception as e:
 59                 success = False
 60                 result = None
 61 
 62             if callback is not None:
 63                 try:
 64                     callback(success, result)
 65                 except Exception as e:
 66                     pass
 67 
 68             with self.worker_state(self.free_list, current_thread):
 69                 if self.terminal:
 70                     event = StopEvent
 71                 else:
 72                     event = self.q.get()
 73         else:
 74 
 75             self.generate_list.remove(current_thread)
 76 
 77     def close(self):
 78         """
 79         执行完所有的任务后,所有线程停止
 80         """
 81         self.cancel = True
 82         full_size = len(self.generate_list)
 83         while full_size:
 84             self.q.put(StopEvent)
 85             full_size -= 1
 86 
 87     def terminate(self):
 88         """
 89         无论是否还有任务,终止线程
 90         """
 91         self.terminal = True
 92 
 93         while self.generate_list:
 94             self.q.put(StopEvent)
 95 
 96         self.q.empty()
 97 
 98     @contextlib.contextmanager
 99     def worker_state(self, state_list, worker_thread):
100         """
101         用于记录线程中正在等待的线程数
102         """
103         state_list.append(worker_thread)
104         try:
105             yield
106         finally:
107             state_list.remove(worker_thread)
108 
109 # How to use
110 
111 
112 pool = ThreadPool(5)
113 
114 def callback(status, result):
115     # status, execute action status
116     # result, execute action return value
117     pass
118 
119 
120 def action(i):
121     print(i)
122 
123 for i in range(30):
124     ret = pool.run(action, (i,), callback)
125 
126 time.sleep(5)
127 print(len(pool.generate_list), len(pool.free_list))
128 print(len(pool.generate_list), len(pool.free_list))
129 # pool.close()
130 # pool.terminate()
高级版本线程池

进程

queues(队列)数据共享

from multiprocessing import Process
from multiprocessing import queues
import multiprocessing

def foo(i, arg):
    arg.put(i)
    print('say hi', i, arg.qsize())

if __name__ == "__main__":
    # li = []
    li = queues.Queue(20, ctx=multiprocessing)
    for i in range(10):
        p = Process(target=foo, args=(i, li,))
        # p.daemon = True
        p.start()
        # p.join()

array(数组)

from multiprocessing import Process
from multiprocessing import queues
import multiprocessing
from multiprocessing import Array

def foo(i, arg):
    arg[i] = i + 100
    for item in arg:
        print(item)
    print('=======================')

if __name__ == "__main__":
    li = Array('i', 10)
for i in range(10):
        p.start()

Manager.dict(字典)

from multiprocessing import Process
from multiprocessing import Manager

def foo(i, arg):
    arg[i] = i + 100
    print(arg.values())

if __name__ == "__main__":
    obj = Manager()
    li = obj.dict()
    for i in range(10):
        p = Process(target=foo, args=(i, li,))
        p.start()
        p.join()
    # p.join() 方式二
# 方式一
import time
time.sleep(1)

进程池

from multiprocessing import Pool
import time
def f1(arg):
    time.sleep(1)
    print(arg)

if __name__ == "__main__": #windows环境下测试需要加此项
    pool =Pool(5)

    for i in range(30): #任务,30
        # pool.apply(func=f1,args=(i,)) #去进程池取任务,串行操作
        pool.apply_async(func=f1,args=(i,)) #去进程池取任务,异步操作
    # pool.close() #所有的任务执行完毕
    # time.sleep(1) 
    # pool.terminate() #立即终止
    # pool.join() #当主进程执行到这里时,需要等待子进程全部执行完成。

进程小结:

IO密集型使用多线程,例如:爬虫

计算密集型:使用多进程

协程

原理:利用一个线程,分解一个线程,成为多个“微线程”(程序级别)。

协程是认为构造出来的,线程和进程是计算机创建的。

greenlet:底层

gevent:更高层

 

greentlet:

from greenlet import greenlet

def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()

def test2():
    print(56)
    gr1.switch()
    print(78)

gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

gevent:

from gevent import monkey;monkey.patch_all()
import gevent
import requests

def f(url):
    print("GET:%S"%url)
    resp = requests.get(url)
    data =resp.text
    print("%d bytes received from %s." %(len(data),url))

gevent.joinall([
       gevent.spawn(f,"https://www.python.org/"),
       gevent.spawn(f,"https://www.yahoo.com/"),
       gevent.spawn(f,"https://github.com/"),
])

 

  

 

 

  

  

  

 

posted @ 2016-07-21 10:27  梁怀军  阅读(187)  评论(0编辑  收藏  举报