创建线程
第一种:
import threading
def f1(arg):
print(arg)

t = threading.Thread(target=f1, args=(123,))
#t.start()准备就绪,等待调度
t.start()
#cpu直接执行run方法
t.run()
第二种:
import threading
class MyThread(threading.Thread):

def __init__(self, func, args):
#自定义构造方法
self.func = func
self.args = args
#调用父类构造方法
super(MyThread, self).__init__()

def run(self):
self.func(self.args)

def f2(arg):
print(arg)

obj = MyThread(f2, 123)
obj.start()

队列:在内存中创建

import queue

#先进先出
q = queue.Queue(10)
#empty判断队列是否为空
print(q.empty())
q.put(11)
q.put(22)
print(q.empty())
# q.put(33)
# q.put(44)
#qsize:队列中的真实个数
#maxsize:最大支持个数
print(q.qsize())
#超时时间
# q.put(55, timeout = 2)
# #默认为阻塞,block=False表示不等待,如果队列满了直接报错
# q.put(66, block=False, timeout = 2)
print(q.get())
q.task_done()
#默认阻塞,block=False不再堵塞
print(q.get(block=False))
q.task_done()
#join队列中的元素还未完成,join阻塞,当队列中任务执行完成之后释放阻塞
q.join()

import queue

#后进先出
#last in first out
q = queue.LifoQueue()
q.put(123)
q.put(456)
print(q.get())

#优先级队列(数据+权重)
q = queue.PriorityQueue()
q.put((1, 'alex1'))
q.put((2, 'alex2'))
q.put((1, 'alex3'))
q.put((4, 'alex4'))
print(q.get())

#双向队列

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

#生产者、消费者模型
import queue,threading,time
q = queue.Queue(20)

def productor(arg):
while True:
q.put(str(arg) + '- 包子')

def consumer(arg):
while True:
print(arg, q.get())
time.sleep(4)

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

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

模拟火车站售票
#生产者、消费者模型:支持瞬时并发数超大的情况
import queue,threading,time
q = queue.Queue(20)

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()

加锁、解锁
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

import threading
import time

NUM = 10

def func(l):
global NUM
#上锁
l.acquire()
NUM -= 1
l.acquire()
time.sleep(1)
l.release()
print(NUM)
# 开锁
l.release()

#只能锁一次
#lock = threading.Lock()
#递归锁,常用
lock = threading.RLock()

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

Event事件
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

import threading

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

#event:将线程批量放行
event = threading.Event()
for i in range(10):
t = threading.Thread(target=func, args=(i, event ,))
t.start()

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

Condition等待:
第一种:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

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

#使得线程等待,只有满足某条件时,才释放n个线程
c = threading.Condition()

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

while True:
inp = input('>>>')
#满足条件时,释放inp个线程
if inp == 'q':
break
c.acquire()
c.notify(int(inp))
c.release()

第二种:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

import threading
def condition():
ret = False
r = input('>>>')
if r == 'true':
ret = True
else:
ret = False
return ret
def func(i, conn):
print(i)
conn.acquire()
# 使得线程等待,只有满足某条件时,才释放n个线程
conn.wait_for(condition)
print(i + 100)
conn.release()

c = threading.Condition()

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

Timer定时器:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

#Timer:定时器
from threading import Timer
def hello():
print('hello Timer')

t = Timer(2, hello)
t.start()

线程池:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

#最简单的线程池
import queue
import threading
import time

class ThreadPool:
def __init__(self, maxsize=5):
self.maxsize = maxsize
self._q = queue.Queue(maxsize)
for i in range(maxsize):
self._q.put(threading.Thread)
#[threading.Thread, threading.Thread, threading.Thread, threading.Thread, threading.Thread]

def get_thread(self):
return self._q.get()

def add_thread(self):
self._q.put(threading.Thread)

pool = ThreadPool(5)
def task(arg, p):
print(arg)
time.sleep(2)
p.add_thread()
for i in range(100):
# t是threading.Thread类
t = pool.get_thread()
#obj对象
obj = t(target=task, args=(i, pool, ))
obj.start()

复杂线程池:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

#!/usr/bin/env python
# -*- coding:utf-8 -*-

import queue
import threading
import contextlib
import time

StopEvent = object()

class ThreadPool(object):

def __init__(self, max_num, max_task_num = None):
if max_task_num:
self.q = queue.Queue(max_task_num)
else:
self.q = queue.Queue()
self.max_num = max_num
self.cancel = False
self.terminal = False
#当前已经创建的线程数
self.generate_list = []
#当前还空闲多少线程,空闲:队列中没有任务
self.free_list = []

def run(self, func, args, callback=None):
"""
线程池执行一个任务
:param func: 任务函数
:param args: 任务函数所需参数
:param callback: 任务执行失败或成功后执行的回调函数,回调函数有两个参数1、任务函数执行状态;2、任务函数返回值(默认为None,即:不执行回调函数)
:return: 如果线程池已经终止,则返回True否则None
"""
if self.cancel:
return
#已经创建的线程小于最大线程数,没有空闲的线程的情况下创建线程
if len(self.free_list) == 0 and len(self.generate_list) < self.max_num:
self.generate_thread()
#把三个参数存放到元祖中
w = (func, args, callback,)
self.q.put(w)

def generate_thread(self):
"""
创建一个线程
"""
t = threading.Thread(target=self.call)
t.start()

def call(self):
"""
循环去获取任务函数并执行任务函数
"""
current_thread = threading.currentThread()
#将当前创建的线程加入到已经创建的线程列表中
self.generate_list.append(current_thread)

#队列中取任务,即在元祖中取(函数, 元祖, 函数)
event = self.q.get()
while event != StopEvent:
#event = (函数, 元祖, 函数)

func, arguments, callback = event
try:
result = func(*arguments)
success = True
except Exception as e:
success = False
result = None

if callback is not None:
try:
callback(success, result)
except Exception as e:
pass

#执行完action,则设置为空闲状态
with self.worker_state(self.free_list, current_thread):
if self.terminal:
event = StopEvent
else:
event = self.q.get()
else:
#event为空,当前线程被移除
self.generate_list.remove(current_thread)

def close(self):
"""
执行完所有的任务后,所有线程停止
"""
self.cancel = True
#获取创建的线程数
full_size = len(self.generate_list)
while full_size:
#设置停止标志
self.q.put(StopEvent)
full_size -= 1

def terminate(self):
"""
无论是否还有任务,终止线程
"""
self.terminal = True

while self.generate_list:
self.q.put(StopEvent)

self.q.queue.clear()

@contextlib.contextmanager
def worker_state(self, state_list, worker_thread):
"""
用于记录线程中正在等待的线程数
"""
state_list.append(worker_thread)
try:
yield
finally:
state_list.remove(worker_thread)

# How to use

pool = ThreadPool(5)

#任务
def callback(status, result):
# status, execute action status
# result, execute action return value
pass

def action(i):
print(i)

#30个任务
for i in range(30):
#pool中的run方法
#函数名,元祖,函数名
ret = pool.run(action, (i,), callback)

time.sleep(5)
print(len(pool.generate_list), len(pool.free_list))
print(len(pool.generate_list), len(pool.free_list))
# pool.close()
# pool.terminate()

进程数据共享:
1、queues方式
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

#内部使用的是os.fork(),windows下不能直接运行
from multiprocessing import Process
#特殊queues,实现进程的数据共享
from multiprocessing import queues
import multiprocessing
import threading
import time

#默认情况下进程的数据不共享
def foo(i, arg):
arg.put(i)
print('say hi', i, arg.qsize())

#windows下最多测试,不能直接使用,*nix下去掉if
if __name__ == '__main__':
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()

2、Array方式

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

#内部使用的是os.fork(),windows下不能直接运行
from multiprocessing import Process
#特殊queues,实现进程的数据共享
from multiprocessing import queues
import multiprocessing

import threading
import time

from multiprocessing import Array

#默认情况下进程的数据不共享
def foo(i, arg):
arg[i] = i + 100
for item in arg:
print(item)
print('==========')

#windows下最多测试,不能直接使用,*nix下去掉if
if __name__ == '__main__':
li = Array('i', 10)
"""
'c': ctypes.c_char, 'u': ctypes.c_wchar,
'b': ctypes.c_byte, 'B': ctypes.c_ubyte,
'h': ctypes.c_short, 'H': ctypes.c_ushort,
'i': ctypes.c_int, 'I': ctypes.c_uint,
'l': ctypes.c_long, 'L': ctypes.c_ulong,
'f': ctypes.c_float, 'd': ctypes.c_double

类型对应表
"""
for i in range(10):
p = Process(target=foo, args=(i, li, ))
#p.daemon = True
p.start()
#p.join()

3、Manager.dict方式
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

"""
进程之间数据共享(掌握3种方式):
1、queues
2、Array
3.Manager.dict
pipe:管道,类似于socket
"""
#内部使用的是os.fork(),windows下不能直接运行
from multiprocessing import Process
from multiprocessing import Manager
import multiprocessing
import threading
import time

from multiprocessing import Array

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

#windows下最多测试,不能直接使用,*nix下去掉if
if __name__ == '__main__':
obj = Manager()
li = obj.dict()
for i in range(10):
p = Process(target=foo, args=(i, li, ))
#p.daemon = True
p.start()
#不加join会导致,主进程执行完成后将主进程和子进程的连接断开,无法实现数据共享
p.join()

进程锁
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

#进程锁
from multiprocessing import Process
from multiprocessing import queues
import multiprocessing
import threading
import time
from multiprocessing import RLock, Lock, Event, Condition, Semaphore

from multiprocessing import Array

def foo(i, lis, lc):
lc.acquire()
lis[0] = lis[0] - 1
time.sleep(1)
print('say hi', lis[0])
lc.release()

if __name__ == '__main__':
li = Array('i', 1)
li[0] = 10
lock = RLock()
for i in range(10):
p = Process(target=foo, args=(i, li, lock, ))
p.start()

进程池:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

"""
进程池
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,
如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。
进程池中有两个方法:
apply
apply_async
"""
from multiprocessing import Pool
import time

def f1(arg):
time.sleep(1)
print(arg)

if __name__ == '__main__':
pool = Pool(5)

for i in range(30):
#pool.apply(func=f1, args=(i, ))
pool.apply_async(func=f1, args=(i, ))
#close:所有的任务全部执行完毕,才终止
#pool.close()
#terminate:立即终止
time.sleep(2)
pool.terminate()
pool.join()
print('end')

总结:IO密集型用多线程(如:爬虫)、计算密集型用多进程。

协程:

greenlet方式:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

"""
协程
线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。
协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。
协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。
协程的适用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;
"""
# !/usr/bin/env python
# -*- coding:utf-8 -*-

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方式:
import gevent

def foo():
print('Running in foo')
gevent.sleep(0)
print('Explicit context switch to foo again')

def bar():
print('Explicit context to bar')
gevent.sleep(0)
print('Implicit context switch back to bar')

gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])

遇到IO操作自动切换:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: wanghuafeng

#monkey.patch_all():把原有socket进行修改,增加发送请求并得到请求的结果
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/'),
])

memcached使用:

#第一次操作
import memcache

#debug = True 表示运行出现错误时,显示错误信息,上线后移除该参数。
mc = memcache.Client(['192.168.113.128:12000'], debug=True)
mc.set('foo','bar')
ret = mc.get('foo')
print(ret)

#天生支持集群
mc = memcache.Client([('192.168.113.128:12000', 1), ('1.1.1.1:12000', 3), ('1.1.1.2:12000', 2), ('1.1.1.3:12000', 4)], debug=True)
mc.set('k1', 'v1')

#增加一条记录
mc = memcache.Client(['192.168.113.128:12000'], debug=True)
mc.add('k5', 'v5')
# mc.add('k1', 'v2') # 报错,对已经存在的key重复添加,失败!!!

#替换
mc = memcache.Client(['192.168.113.128:12000'], debug=True)
# 如果memcache中存在k1,则替换成功,否则一场
mc.replace('k1','999')
val = mc.get('k1')
print(val)

#设置一个键值对
mc = memcache.Client(['192.168.113.128:12000'], debug=True)
mc.set('key7', 'wanghuafeng')
val = mc.get('key7')
print(val)

#设置多个键值对
mc = memcache.Client(['192.168.113.128:12000'], debug=True)
mc.set_multi({'key8': 'val8', 'key9': 'val9'})
item_dict = mc.get_multi(["key8", "key9"])
print(item_dict)

#get 获取一个键值对
#get_multi 获取多一个键值对
mc = memcache.Client(['192.168.113.128:12000'], debug=True)
val = mc.get('key0')
item_dict = mc.get_multi(["key1", "key2", "key3"])

#append 修改指定key的值,在该值 后面 追加内容
#prepend 修改指定key的值,在该值 前面 插入内容
mc = memcache.Client(['192.168.113.128:12000'], debug=True)
mc.prepend('k1', 'before')
val = mc.get('k1')
print(val)

#incr 自增,将Memcached中的某一个值增加 N ( N默认为1 )
#decr 自减,将Memcached中的某一个值减少 N ( N默认为1 )
mc.set('k1', '777')
mc.incr('k1')
val = mc.get('k1')
print(val)

mc.incr('k1', 10)
val = mc.get('k1')
print(val)

mc.decr('k1')
val = mc.get('k1')
print(val)
mc.decr('k1', 10)
val = mc.get('k1')
print(val)

#delete 在Memcached中删除指定的一个键值对
#delete_multi 在Memcached中删除指定的多个键值对

mc = memcache.Client(['192.168.113.128:12000'], debug=True)
mc.delete('key0')
mc.delete_multi(['key1', 'key2'])

#本质上每次执行gets时,会从memcache中获取一个自增的数字,
通过cas去修改gets的值时,会携带之前获取的自增值和memcache中的自增值进行比较,
如果相等,则可以提交,如果不想等,那表示在gets和cas执行之间,
又有其他人执行了gets(获取了缓冲的指定值), 如此一来有可能出现非正常数据,则不允许修改。
mc = memcache.Client(['192.168.113.128:12000'], debug=True, cache_cas=True)
v = mc.gets('product_count')
# 如果有人在gets之后和cas之前修改了product_count,那么,下面的设置将会执行失败,剖出异常,从而避免非正常数据的产生
mc.cas('product_count', "899")

Day11 线程、进程、协程的更多相关文章

  1. 学到了林海峰,武沛齐讲的Day34 完 线程 进程 协程 很重要

    线程 进程 协程 很重要 ...儿子满月回家办酒,学的有点慢,坚持

  2. 文成小盆友python-num11-(1) 线程 进程 协程

    本节主要内容 线程补充 进程 协程 一.线程补充 1.两种使用方法 这里主要涉及两种使用方法,一种为直接使用,一种为定义自己的类然后继承使用如下: 直接使用如下: import threading d ...

  3. Python学习笔记整理总结【网络编程】【线程/进程/协程/IO多路模型/select/poll/epoll/selector】

    一.socket(单链接) 1.socket:应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socke ...

  4. python_21_线程+进程+协程

    python_线程_进程_协程 什么是线程? -- os能够进行运算调度的最小单位,被包含在进程之中,是一串指令的集合 -- 每个线程都是独立的,可以访问同一进程下所有的资源 什么是进程? -- 每个 ...

  5. 线程&进程&协程

    线程 线程是应用程序中工作的最小单元,它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务.Threading用 ...

  6. 15.python并发编程(线程--进程--协程)

    一.进程:1.定义:进程最小的资源单位,本质就是一个程序在一个数据集上的一次动态执行(运行)的过程2.组成:进程一般由程序,数据集,进程控制三部分组成:(1)程序:用来描述进程要完成哪些功能以及如何完 ...

  7. python 线程 进程 协程 学习

    转载自大神博客:http://www.cnblogs.com/aylin/p/5601969.html 仅供学习使用···· python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和 ...

  8. python之并发编程(线程\进程\协程)

    一.进程和线程 1.进程 假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源.是 ...

  9. python中线程 进程 协程

    多线程:#线程的并发是利用cpu上下文的切换(是并发,不是并行)#多线程执行的顺序是无序的#多线程共享全局变量#线程是继承在进程里的,没有进程就没有线程#GIL全局解释器锁#只要在进行耗时的IO操作的 ...

  10. Python学习之路--进程,线程,协程

    进程.与线程区别 cpu运行原理 python GIL全局解释器锁 线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生产者消费者模型 Q ...

随机推荐

  1. CMS收集器

    CMS收集周期 CMS并非没有暂停,而是用两次短暂停来替代串行标记整理算法的长暂停,它的收集周期是这样:初始标记(CMS-initial-mark) -> 并发标记(CMS-concurrent ...

  2. Java开发中文件读取方式总结

    JAVA开发中,免不了要读文件操作,读取文件,首先就需要获取文件的路径. 路径分为绝对路径和相对路径. 在文件系统中,绝对路径都是以盘符开始的,例如C:\abc\1.txt. 什么是相对路径呢?相对路 ...

  3. 【Android笔记】MediaPlayer基本使用方式

    Android MediaPlayer基本使用方式 使用MediaPlayer播放音频或者视频的最简单样例: JAVA代码部分: public class MediaPlayerStudy exten ...

  4. [Angular 2] 9. Replace ng-modle with #ref & events

    Let's say you want to write a simple data bing app. when you type in a text box, somewhere in the ap ...

  5. Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换

    如何调用本地图片,并调用系统拍摄的图像上一博文解释(http://blog.csdn.net/a123demi/article/details/40003695)的功能. 而本博文将通过实例实现自己定 ...

  6. [CodeForce]358D Dima and Hares

    有N<3000只宠物要喂,每次只能喂一只,每喂一只宠物,宠物的满足度取决于: 1 紧靠的两个邻居都没喂,a[i] 2 邻居中有一个喂过了,b[i] 3 两个邻居都喂过了,c[i] 把所有宠物喂一 ...

  7. Qt 学习之路:Qt 简介

    Qt 是一个著名的 C++ 应用程序框架.你并不能说它只是一个 GUI 库,因为 Qt 十分庞大,并不仅仅是 GUI 组件.使用 Qt,在一定程度上你获得的是一个“一站式”的解决方案:不再需要研究 S ...

  8. android开发之使用Messenger实现service与activity交互

    service与activity交互的方式有多种,这里说说使用Messenger来实现两者之间的交互. Service程序 public class MessengerService extends ...

  9. CUDA与VS2013安装

    @import url(http://i.cnblogs.com/Load.ashx?type=style&file=SyntaxHighlighter.css);@import url(/c ...

  10. 初识 Angular 体会

    一句话描述:一个前端的类似MVC框架的JS库 刚接触2天,刚一看感觉和asp.net mvc能实现的功能有点重复. 虽然asp.net的表单验证,Razor语法使其在前端开发有较大提升,但要实现比较高 ...