python多线程、多进程模块

单线程:

import time
import threading

def music(name,loop):
    for i in range(loop):
        print("listen music {} {}".format(name,time.ctime()))
        time.sleep(1)

def movie(name,loop):
    for i in range(loop):
        print("look movie {} {}".format(name,time.ctime()))
        time.sleep(1)

if __name__ == "__main__":
    music("爱转角",5)
    movie("小王子",4)
    print("end time",time.ctime())

多线程:

import time
import threading

def music(name,loop):
    for i in range(loop):
        print("listen music {} {}".format(name,time.ctime()))
        time.sleep(1)

def movie(name,loop):
    for i in range(loop):
        print("look movie {} {}".format(name,time.ctime()))
        time.sleep(1)

# 创建多线程
t1 = threading.Thread(target=music,args=("爱转角",5))
t2 = threading.Thread(target=movie,args=("小王子",4))

if __name__ == "__main__":
    # 启动线程
    t1.start()
    t2.start()
    # print("end time",time.ctime())

import time
import threading

def music(name,loop):
    for i in range(loop):
        print("listen music {} {} {}".format(name,time.ctime(),threading.Thread.getName(t1)))
        time.sleep(1)

def movie(name,loop):
    for i in range(loop):
        print("look movie {} {} {}".format(name,time.ctime(),threading.Thread.name))
        time.sleep(1)

# 创建多线程
t1 = threading.Thread(target=music,args=("爱转角",5))
t1.setName("线程1")
t2 = threading.Thread(target=movie,args=("小王子",4),)
# t2.setName("线程2")

if __name__ == "__main__":
    # 启动线程
    t1.start()
    t2.start()
    # print("end time",time.ctime())
look movie 小王子 Sat Jul  6 08:19:37 2019 <property object at 0x000002656EF79728>
listen music 爱转角 Sat Jul  6 08:19:38 2019 线程1
look movie 小王子 Sat Jul  6 08:19:38 2019 <property object at 0x000002656EF79728>
listen music 爱转角 Sat Jul  6 08:19:39 2019 线程1
look movie 小王子 Sat Jul  6 08:19:39 2019 <property object at 0x000002656EF79728>
look movie 小王子 Sat Jul  6 08:19:40 2019 <property object at 0x000002656EF79728>
listen music 爱转角 Sat Jul  6 08:19:40 2019 线程1
listen music 爱转角 Sat Jul  6 08:19:41 2019 线程1

线程守护,主线程结束,杀死子线程

import time
import threading

def music(name,loop):
    for i in range(loop):
        print("listen music {} {} {}".format(name,time.ctime(),threading.Thread.getName(t1)))
        time.sleep(1)

def movie(name,loop):
    for i in range(loop):
        print("look movie {} {} {}".format(name,time.ctime(),threading.Thread.name))
        time.sleep(1)

# 创建多线程
t1 = threading.Thread(target=music,args=("爱转角",5))
t1.setName("线程1")
t2 = threading.Thread(target=movie,args=("小王子",4),)
# t2.setName("线程2")


if __name__ == "__main__":
    # 守护主线程   主线程结束,杀死子线程
    t1.setDaemon(True)
    t2.setDaemon(True)

    # 启动线程
    t1.start()
    t2.start()
    print("主线程:",time.ctime())
listen music 爱转角 Sat Jul  6 08:29:43 2019 线程1
look movie 小王子 Sat Jul  6 08:29:43 2019 <property object at 0x00000254F7629728>
主线程: Sat Jul  6 08:29:43 2019

GIL全局锁:相当于python 单线程,不适合大的数据量

import threading

balace =0

def change(n):
    global balace
    balace += n
    balace -= n


lock = threading.Lock()#获取线程锁
def run_thread(n):
    for i in range(1000000):
        #获取锁
        lock.acquire()
        try:
            change(n)
        finally:
            # 释放锁
            lock.release()


t1 = threading.Thread(target=run_thread,args=(4,))
t2 = threading.Thread(target=run_thread,args=(8,))

t1.start()
t2.start()
t1.join()
t2.join()
print(balace)

多进程及加锁:

import time
import multiprocessing

def music(name,loop,lock):
    lock.acquire()
    for i in range(loop):
        print("listen music {} {}".format(name,time.ctime()))
        time.sleep(1)
    lock.release()

def movie(name,loop,lock):
    lock.acquire()
    for i in range(loop):
        print("look movie {} {}".format(name,time.ctime()))
        time.sleep(1)
    lock.release()

if __name__ == "__main__":
    lock = multiprocessing.Lock()
    t1 = multiprocessing.Process(target=music, args=("爱转角", 5, lock))
    t2 = multiprocessing.Process(target=movie, args=("小王子", 4, lock))
    t1.start()
    t2.start()
listen music 爱转角 Sat Jul  6 09:09:57 2019
listen music 爱转角 Sat Jul  6 09:09:58 2019
listen music 爱转角 Sat Jul  6 09:09:59 2019
listen music 爱转角 Sat Jul  6 09:10:00 2019
listen music 爱转角 Sat Jul  6 09:10:01 2019
look movie 小王子 Sat Jul  6 09:10:02 2019
look movie 小王子 Sat Jul  6 09:10:03 2019
look movie 小王子 Sat Jul  6 09:10:04 2019
look movie 小王子 Sat Jul  6 09:10:05 2019

多进程池:

Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行它

进程池方法: 

apply(func[, args[, kwds]])阻塞的执行,比如创建一个有3个线程的线程池,当执行时是创建完一,执行函数再创建另一个,变成一个线性的执行.  apply_async(func[, args[, kwds[, callback]]]) 它是非阻塞执行,同时创建3个线程的线城池,同时执行,只要有一个执行完立刻放回池子待下一个执行,并行的执行 .

close()关闭pool,使其不在接受新的任务。 

terminate() 结束工作进程,不在处理未完成的任务。 

join(): 主进程阻塞,等待子进程的退出, join方法要在closeterminate之后使用

# 进程池
import multiprocessing
import os
import time


def work1(n):
    print("run work {},work id {}".format(n,os.getpid()))
    time.sleep(2)
    print("work {} stop,work id {}".format(n,os.getpid()))


if __name__ == "__main__":
    print("Parent process {}".format(os.getpid()))
    p = multiprocessing.Pool(3)
    for i in range(10):
        p.apply_async(work1,args=(i,))
    p.close()
    p.join()
Parent process 17352
run work 0,work id 13244
run work 1,work id 4764
run work 2,work id 15784

work 0 stop,work id 13244
run work 3,work id 13244

work 1 stop,work id 4764
run work 4,work id 4764

work 2 stop,work id 15784
run work 5,work id 15784

work 3 stop,work id 13244
run work 6,work id 13244

work 4 stop,work id 4764
run work 7,work id 4764

work 5 stop,work id 15784
run work 8,work id 15784

work 6 stop,work id 13244
run work 9,work id 13244

work 7 stop,work id 4764
work 8 stop,work id 15784
work 9 stop,work id 13244

队列(Queue

      进程彼此之间互相隔离,要实现进程间通信(IPC,multiprocessing模块支持两种形式:队列Queue和管道Pipe这两种方式都是使用消息传递的

创建队列的类(底层就是以管道和锁定的方式实现)

Queue([maxsize]):创建共享的进程队列,Queue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。      

参数介绍:maxsize是队列中允许最大项数,省略则无大小限制

q.put方法用以插入数据到队列中

put方法还有两个可选参数:blockedtimeout。如果blockedTrue(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blockedFalse,但该Queue已满,会立即抛出Queue.Full异常。

q.get方法可以从队列读取并且删除一个元素

同样get方法有两个可选参数:blockedtimeout。如果blockedTrue(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blockedFalse,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常.

q.get_nowait():q.get(False)

q.put_nowait():q.put(False)

q.empty():调用此方法时q为空则返回True,该结果不可靠,比如在返回True的过程中,如果队列中又加入了项目

q.full():调用此方法时q已满则返回True,该结果不可靠,比如在返回True的过程中,如果队列中的项目被取走。

q.qsize():返回队列中目前项目的正确数量,结果也不可靠,理由同上

# 跨进程通信
import multiprocessing
import time

def put_(q):
    for value in ['a','b','c']:
        print('发送{}到queue。。。'.format(value))
        q.put(value)
        time.sleep(2)

def get_(q):
    while True:
        value = q.get(True)
        print('从queue接收{}'.format(value))

if __name__ == "__main__":
    q = multiprocessing.Queue()
    pw = multiprocessing.Process(target=put_,args=(q,))
    pr = multiprocessing.Process(target=get_,args=(q,))
    # 启动子进程,写入
    pw.start()
    # 启动子进程pr,读取
    pr.start()
    pw.join()

    #pr 进程是死循环,无法等待其结束;当get无法得到数据时,强制终止
    pr.terminate()
发送a到queue。。。
从queue接收a
发送b到queue。。。
从queue接收b
发送c到queue。。。
从queue接收c

管道(pipe):

Pipe方法返回(conn1, conn2)代表一个管道的两个端。Pipe方法有duplex参数:duplex True(默认值),那么这个管道是全双工模式,也就是说conn1conn2均可收发duplex Falseconn1只负责接受消息,conn2只负责发送消息

sendrecv方法分别是发送和接收消息的方法。在全双工模式下,可以调用conn1.send发送消息,conn1.recv接收消息。如果没有消息可接收,recv方法会一直阻塞。如果管道已经被关闭,那么recv方法会抛出EOFError

# 左边接收,右边发送
import multiprocessing
import time

def send_(q):
    for value in ['a','b','c']:
        print('发送{}到pipe。。。,{}'.format(value,time.ctime()))
        q[1].send(value)
        time.sleep(2)

def recv_(q):
    while True:
        value = q[0].recv()
        print('从pipe接收{}   {}'.format(value,time.ctime()))

if __name__ == "__main__":
    p = multiprocessing.Pipe(duplex=False)
    pw = multiprocessing.Process(target=send_,args=(p,))
    pr = multiprocessing.Process(target=recv_,args=(p,))
    pw.start()
    pr.start()
    pw.join()
    pr.terminate()
发送a到pipe。。。,Sat Jul  6 15:42:44 2019
从pipe接收a   Sat Jul  6 15:42:44 2019
发送b到pipe。。。,Sat Jul  6 15:42:46 2019
从pipe接收b   Sat Jul  6 15:42:46 2019
发送c到pipe。。。,Sat Jul  6 15:42:48 2019
从pipe接收c   Sat Jul  6 15:42:48 2019

生产者消费者:

import threading
import time
import queue

q = queue.Queue(maxsize=10)
def producer(name):
    count = 1
    while True:
        q.put("骨头{}".format(count))
        print('生产了骨头{}  {}'.format(count,time.ctime()))
        count += 1
        time.sleep(0.5)

def consumer(name):
    while True:
        print('{}取到{}并且吃了它。。。。 {}'.format(name,q.get(),time.ctime()))
        time.sleep(1)

p = threading.Thread(target=producer,args=("tim",))
c1 = threading.Thread(target=consumer,args=("king",))
c2 = threading.Thread(target=consumer,args=("wang",))
p.start()
c1.start()
c2.start()
生产了骨头1  Sat Jul  6 15:44:29 2019
king取到骨头1并且吃了它。。。。 Sat Jul  6 15:44:29 2019
生产了骨头2  Sat Jul  6 15:44:30 2019
wang取到骨头2并且吃了它。。。。 Sat Jul  6 15:44:30 2019
生产了骨头3  Sat Jul  6 15:44:30 2019
king取到骨头3并且吃了它。。。。 Sat Jul  6 15:44:30 2019
生产了骨头4  Sat Jul  6 15:44:31 2019
wang取到骨头4并且吃了它。。。。 Sat Jul  6 15:44:31 2019
生产了骨头5  Sat Jul  6 15:44:31 2019
king取到骨头5并且吃了它。。。。 Sat Jul  6 15:44:31 2019
生产了骨头6  Sat Jul  6 15:44:32 2019
wang取到骨头6并且吃了它。。。。 Sat Jul  6 15:44:32 2019

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值