python进程里加入线程_python之线程、进程

本文介绍了Python中的线程和进程概念,包括线程的创建、执行方式、守护线程、线程锁、信号量、定时器、队列以及生产者消费者模型。详细讲解了线程的使用和线程间通信的方法,还探讨了进程间通信的多种方式,如queue、pipe和锁等。
摘要由CSDN通过智能技术生成

线程语法

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

结果:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值