python之线程、进程
线程语法
class Thread(_Verbose):
"""A class that represents a thread of control. This class can be safely subclassed in a limited fashion. """
__initialized = False
# Need to store a reference to sys.exc_info for printing
# out exceptions when a thread tries to use a global var. during interp.
# shutdown and thus raises an exception about trying to perform some
# operation on/with a NoneType
__exc_info = _sys.exc_info
# Keep sys.exc_clear too to clear the exception just before
# allowing .join() to return.
__exc_clear = _sys.exc_clear def __init__(self, group=None, target=None, name=None,
args=(), kwargs=None, verbose=None):
"""This constructor should always be called with keyword arguments. Arguments are: *group* should be None; reserved for future extension when a ThreadGroup
class is implemented. *target* is the callable object to be invoked by the run()
method. Defaults to None, meaning nothing is called. *name* is the thread name. By default, a unique name is constructed of
the form "Thread-N" where N is a small decimal number. *args* is the argument tuple for the target invocation. Defaults to (). *kwargs* is a dictionary of keyword arguments for the target
invocation. Defaults to {}. If a subclass overrides the constructor, it must make sure to invoke
the base class constructor (Thread.__init__()) before doing anything
else to the thread. """
assert group is None, "group argument must be None for now"
_Verbose.__init__(self, verbose)
if kwargs is None:
kwargs = {}
self.__target = target
self.__name = str(name or _newname())
self.__args = args
self.__kwargs = kwargs
self.__daemonic = self._set_daemon()
self.__ident = None
self.__started = Event()
self.__stopped = False
self.__block = Condition(Lock())
self.__initialized = True
# sys.stderr is not stored in the class like
# sys.exc_info since it can be changed between instances
self.__stderr = _sys.stderr
……
线程
线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
1、直接调用
2、继承调用:先继承原类,再重写其中的run方法
3、线程并行执行:join阻塞,直到此进程执行完毕再往下继续执行
4、守护线程
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
__Author__ = 'KongZhaGen'
import threading
import time # 定义用于线程执行的函数
def sayhi(num):
print "runing on number :%s"%num
time.sleep(3)
print 'done',num # main函数同时执行5个线程
def main():
for i in range(5):
t = threading.Thread(target=sayhi,args=(i,))
t.start() # 定义一个线程m,执行main函数
m = threading.Thread(target=main,args=())
# m线程定义为守护线程
m.setDaemon(True)
m.start()
# 守护线程执行结束,其中的所有子线程全部被迫结束运行,接着继续执行其后的代码
m.join(timeout=2)
print "---------main thread done-----"
5、线程锁
无线程锁的情况
一个进程下可以启动多个线程,多个线程共享父进程的内存空间,也就意味着每个线程可以访问同一份数据,此时,如果2个线程同时要修改同一份数据,会出现什么状况?
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen' import time
import threading def addNum():
global num
print '---getNum--',num
time.sleep(1)
num -= 1 num = 100
thread_list = []
for i in range(100):
t = threading.Thread(target=addNum) # 同时开启100个线程
t.start()
thread_list.append(t) for t in thread_list:
t.join() print "final num",num
其结果是:一会为0,一会为其它值
加线程锁后...
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen' import time
import threading def addNum():
global num
print '---getNum--',num
time.sleep(1)
lock.acquire() # 数据修改前加锁
num -= 1
lock.release() # 数据修改后释放锁 num = 100
thread_list = []
lock = threading.Lock() # 生成全局锁 for i in range(100):
t = threading.Thread(target=addNum) # 同时开启100个线程
t.start()
thread_list.append(t) for t in thread_list:
t.join() print "final num",num
其结果一直为0,说明锁起了作用。
Semaphore(信号量)
互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据
定时器
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
import threading def hello():
print "Hello Word.." t = threading.Timer(20,hello) # 20秒钟之后执行hello函数
t.start()
队列Queue
Queue.qsize() 返回队列的大小
Queue.empty() 如果队列为空,返回True,反之False
Queue.full() 如果队列满了,返回True,反之False
Queue.full 与 maxsize 大小对应
Queue.get([block[, timeout]])获取队列,timeout等待时间
Queue.get_nowait() 相当Queue.get(False)
非阻塞 Queue.put(item) 写入队列,timeout等待时间
Queue.put_nowait(item) 相当Queue.put(item, False)
Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
Queue.join() block直到queue被消费完毕
先进先出 :Queue.Queue
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
import Queue q = Queue.Queue(maxsize=3)
q.put(1)
q.put(3)
q.put(4)
# q.put(7) # 超出三个会阻塞 print q.get() # 1
print q.get() # 3
print q.get() # 4 # 先进先出
q.put(7)
print q.get()
后进先出:Queue.LifoQueue
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
import Queue q = Queue.LifoQueue(maxsize=3)
q.put(1)
q.put(7)
q.put(4) print q.get() # 4
print q.get() # 7
print q.get() # 1
# 结果:后进先出
设置队列优先级:Queue.PriorityQueue
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
import Queue q = Queue.PriorityQueue(maxsize=4)
print q.empty() # 空队列
print q.qsize() # 队列个数0
q.put((1,5))
q.put((5,1))
print q.qsize() # 队列个数2
print q.full() # 队列未满
q.put((3,6))
print q.full() # 队列未满
q.put((2,6))
print q.full() # 队列已满
# q.put_nowait(10) # 队列满后再填入不阻塞,直接报错 print q.get() # 1
print q.get() # 2
print q.get() # 3
print q.get() # 5
# 结果:优先小的先出
print q.get_nowait() # 队列为空后再取出不阻塞,直接报错
生产者消费者模型
在并发编程中使用生产者和消费者模式能够解决绝大多数并发问题。该模式通过平衡生产线程和消费线程的工作能力来提高程序的整体处理数据的速度。
为什么要使用生产者和消费者模式
在线程世界里,生产者就是生产数据的线程,消费者就是消费数据的线程。在多线程开发当中,如果生产者处理速度很快,而消费者处理速度很慢,那么生产者就必须等待消费者处理完,才能继续生产数据。同样的道理,如果消费者的处理能力大于生产者,那么消费者就必须等待生产者。为了解决这个问题于是引入了生产者和消费者模式。
什么是生产者消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
最基本的例子(一个生产者,一个消费者)
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
import Queue
import threading
import time # 生产者
def producer():
for i in range(5):
q.put(i) # 往队列放15个面包
print "等待取走面包....\n"
q.join() # 阻塞直到队列消费完毕
print "面包被全部取走...\n" # 消费者
def consumer(n):
# 队列不为空则一直消费
while q.qsize() > 0:
print "%s 取走面包 %s"%(n, q.get())
q.task_done() # 告诉queue完成了一次消费,完成消费次数等于qsize,队列消费完毕,join取消阻塞
time.sleep(1) q = Queue.Queue() p = threading.Thread(target=producer,)
p.start() c = threading.Thread(target=consumer, args=(['小鬼']))
c.start()
结果:
等待取走面包....
小鬼 取走面包 0
小鬼 取走面包 1
小鬼 取走面包 2
小鬼 取走面包 3
小鬼 取走面包 4
面包被全部取走...
多个生产者与消费者
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
import Queue
import threading
import time,random q = Queue.Queue()
# 生产者
def producer(n):
count = 0
# 少于5个面包就生产
while count < 5:
time.sleep(random.randrange(3))
q.put(count)
print "%s product 面包"%n
count += 1
print "%s 已生产面包%s" %(n, q.qsize()) def consumer(n):
while True:
time.sleep(random.randrange(4))
# 有面包就消费
if not q.empty():
print "\033[31;1m%s 吃了 面包 %s\033[0m"%(n, q.get())
else:
# 没面包就退出
print "没有面包了..."
break p1 = threading.Thread(target=producer, args=(['厨师1']))
p2 = threading.Thread(target=producer, args=(['厨师2']))
p1.start()
p2.start() c1 = threading.Thread(target=consumer, args=(['客户1']))
c2 = threading.Thread(target=consumer, args=(['客户2']))
c1.start()
c2.start()
进程间通迅
queue
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen' from multiprocessing import Process,Queue
import time
q = Queue()
# 往队列传入三个值
def pro_put(q):
q.put(1)
q.put(2)
q.put(3) if __name__ == '__main__':
# 开始一个新进程
p = Process(target=pro_put, args=(q,))
p.start()
# 从队列获取原进程的数据
print q.get()
print q.get()
print q.get()
pipe
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen' from multiprocessing import Process,Pipe def f(conn):
# 往管道发送
conn.send(1)
conn.send(2)
conn.send(3)
conn.close() if __name__ == '__main__':
# Pipe 分两端,任何一端send, 任何一端recv
con_left, con_right = Pipe()
p = Process(target=f, args=(con_right,))
p.start()
# 从管道接收原进程生成的数据
print con_left.recv()
print con_left.recv()
print con_left.recv()
p.join()
进程同步
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen' from multiprocessing import Process, Lock
import time def f(l, i):
# 当多个进程需要访问共享资源的时候,Lock可以用来避免访问的冲突
l.acquire() # Lock实现进程同步进行
try:
print "hello, ",i
finally:
l.release() if __name__ == '__main__':
lock = Lock()
for num in range(10):
Process(target=f, args=(lock, num)).start()
进程池
非阻塞进程池
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
from multiprocessing import Pool
import time,os
print 'parent:',os.getpid() def f(msg):
print 'child:',os.getpid()
print "start:",msg
time.sleep(2)
print "end :",msg
print "============" if __name__ == '__main__':
# 进程池最大数量2
pool = Pool(2)
for i in range(5):
msg = "hello %s" % i
# 同时启动5个进程
pool.apply_async(func=f, args=(msg,)) print "---------------------"
pool.close()
pool.join()
结果:
阻塞进程池
#!/usr/bin/env python
# -*- coding:utf-8 -*-
__Author__ = 'kongZhaGen'
from multiprocessing import Pool
import time def f(msg):
print "start:",msg
time.sleep(2)
print "end :",msg
print "============" if __name__ == '__main__':
# 进程池最大数量2
pool = Pool(2)
for i in range(5):
msg = "hello %s" % i
# 同时启动5个进程
pool.apply(func=f, args=(msg,)) print "---------------------"
pool.close()
pool.join()
结果:
python之线程、进程的更多相关文章
- python之线程进程协成
线程与进程 什么是线程 线程是进程一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源,但是它可与同属一个线程的 ...
- Python(线程进程3)
四 协程 协程,又称微线程,纤程.英文名Coroutine.一句话说明什么是线程:协程是一种用户态的轻量级线程. 协程拥有自己的寄存器上下文和栈.协程调度切换时,将寄存器上下文和栈保存到其他地方,在切 ...
- Python之线程&进程
线程: 线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. thr ...
- Python(线程进程2)
新进程的创建都是由一个已经存在的进程执行了一个用于创建进程的系统调用而创建的: 1. 在UNIX中该系统调用是:fork,fork会创建一个与父进程一模一样的副本,二者有相同的存储映像.同样的环境字符 ...
- python中线程 进程 协程
多线程:#线程的并发是利用cpu上下文的切换(是并发,不是并行)#多线程执行的顺序是无序的#多线程共享全局变量#线程是继承在进程里的,没有进程就没有线程#GIL全局解释器锁#只要在进行耗时的IO操作的 ...
- Python之线程、进程和协程
python之线程.进程和协程 目录: 引言 一.线程 1.1 普通的多线程 1.2 自定义线程类 1.3 线程锁 1.3.1 未使用锁 1.3.2 普通锁Lock和RLock 1.3.3 信号量(S ...
- python中的进程、线程(threading、multiprocessing、Queue、subprocess)
Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CP ...
- Python之路-python(paramiko,进程和线程的区别,GIL全局解释器锁,线程)
一.paramiko 二.进程.与线程区别 三.python GIL全局解释器锁 四.线程 语法 join 线程锁之Lock\Rlock\信号量 将线程变为守护进程 Event事件 queue队列 生 ...
- Python学习--17 进程和线程
线程是最小的执行单元,而进程由至少一个线程组成.如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多长时间. 进程 fork调用 通过fork()系统调用,就可以生成一个子进程 ...
- Python 浅析线程(threading模块)和进程(process)
线程是操作系统能够进行运算调度的最小单位.它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务 进程与线程 什么 ...
随机推荐
- Git-基本操作(图文)
场景一: 已经用git add 命令把文件加入到暂存区了,这个时候想退回怎么办? 添加文件到暂存区 :git add . 将单个文件撤回到工作区:git rm --cached [文件路径] 将目录撤 ...
- 使用EntityFrameworkCore 连接 MySql
上篇文章介绍了如何在dotnetcore下使用Dapper连接MySql,这里再介绍使用使用EntityFrameworkCore 连接 MySql. 新建控制台项目,安装下面两个nuget包: In ...
- 【数组】Spiral Matrix II
题目: Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. ...
- linux一键安装php环境
1.下载一键安装包: http://pan.baidu.com/s/1o6lWyeu 2.unzip -x sh.zip chmod -R 755 sh ./install.sh 等待半小时左右 3. ...
- 【转】Spark源码分析之-deploy模块
原文地址:http://jerryshao.me/architecture/2013/04/30/Spark%E6%BA%90%E7%A0%81%E5%88%86%E6%9E%90%E4%B9%8B- ...
- Linux运维中遇到的常见问题
1.CentOS启动tomcat出现乱码的解决方案1.打开tomcat下的server.xml配置文件,在connect标签中添加编码属性:URIEncoding="UTF-8"2 ...
- Ubuntu-16.04 R 安装及Jupyter notebook 配置
1. R 安装 通常在Terminal下直接apt-get 即可,在16.10下可以get到R-3.3.1,目前最新好像是 R-3.4.2,可以去官方网站下载源码编译 (https://www.r-p ...
- Nodejs学习笔记(十)—与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门
简介 MongoDB 开源,高性能的NoSQL数据库:支持索引.集群.复制和故障转移.各种语言的驱动程序:高伸缩性: NoSQL毕竟还处于发展阶段,也有说它的各种问题的:http://coolshel ...
- 关于Mysql+EF6本地运行和发布没有问题,发布到服务器上出现问题的解决方案
这个问题折磨了我差不多两天,网上各种方法也找了个遍,但是都没有解决我的问题,后面通过自己仔细分析问题和排查,终于把问题解决了,以下是我的解决问题的步骤,希望能帮到各位,不要再被这些问题坑了 1,项目实 ...
- 【模板】埃拉托色尼筛法 && 欧拉筛法 && 积性函数
埃拉托色尼筛法 朴素算法 1 vis[1]=1; 2 for (int i=2;i<=n;i++) 3 if (!vis[i]) 4 { 5 pri[++tot]=i; 6 for (int j ...