Python核心编程第四章总结

Python核心编程

第四章总结(I/O密集型使用多线程,计算密集型使用多进程)

  1. time.sleep()需要一个浮点型参数来指明这个程序会暂停指定的时间。
  2. thread模块
  • start_new_thread(function, args, kwargs = None)
    派生一个新的线程,参数包括函数名,函数的参数,和可选的关键字参数。即使要执行的函数不需要参数,也需要传递一个空元组。
  • allocate_lock()
    分配LockType锁对象
  • exit()
    退出线程

LockType锁对象的方法

  • acquire(wait = None)
    尝试获取锁对象
  • locked()
    如果获取了锁对象则返回True,否则返回False
  • release()
    释放锁
import thread
from time import sleep, ctime

def loop0():
    print('start loop 0 at:', ctime())
    sleep(4)
    print('loop 0 done at:', ctime())

def loop1():
    print('start loop 1 at:', ctime())
    #thread.start_new_thread(loop3,())
    sleep(2)
    print('loop 1 done at:', ctime())
    
'''
def loop3():
    print('start loop 3 at:',ctime())
    sleep(1)
    print('loop 3 done at:', ctime())
'''

def main():
    print('starting at:', ctime())
    thread.start_new_thread(loop0,())
    thread.start_new_thread(loop1,())
    sleep(6)
    print('all DONE at:', ctime())

if __name__ == '__main__':
    main()
starting at: Sun Mar 21 21:00:05 2021
start loop 0 at: Sun Mar 21 21:00:05 2021
start loop 1 at: Sun Mar 21 21:00:05 2021
loop 1 done at: Sun Mar 21 21:00:07 2021
loop 0 done at: Sun Mar 21 21:00:09 2021
all DONE at: Sun Mar 21 21:00:11 2021

主线程之所以有一个sleep(6)是因为如果没有,主线程执行完语句之后会退出,而loop0和loop1会直接终止。

此时我们可以添加锁对象而不必额外延时6秒。先为每个线程获取锁对象,判断每个线程是否释放了锁,释放则结束。

import thread
from time import sleep, ctime

loops = [4, 2]

def loop(nloop, nsec, lock):
    print('start loop', nloop, 'at:', ctime())
    sleep(nsec)
    print('loop', nloop, 'done at:', ctime())
    lock.release()

def main():
    print('starting at:', ctime())
    locks = []
    nloops = range(len(loops))

    for i in nloops:
        lock = thread.allocate_lock()       #获取锁对象
        lock.acquire()                      #把锁锁上
        locks.append(lock)

    for i in nloops:
        thread.start_new_thread(loop,(i, loops[i], locks[i]))

    for i in nloops:
        while locks[i].locked():pass
        
    print('all DONE at:', ctime())

if __name__ == '__main__':
    main()

starting at: Sun Mar 21 21:10:53 2021
start loop 0 at: Sun Mar 21 21:10:53 2021
start loop 1 at: Sun Mar 21 21:10:53 2021
loop 1 done at: Sun Mar 21 21:10:55 2021
loop 0 done at: Sun Mar 21 21:10:57 2021
all DONE at: Sun Mar 21 21:10:57 2021
  1. threading模块
  • Thread类

属性:

name线程名
ident线程的标识符
daemon布尔标志,表示这个线程是否为守护线程

方法:

__init __实例化一个线程对象
start()开始执行该线程
run()定义线程功能的方法(通常在子类中重写)
join(timeout = None)直至启动的线程终止之前一直挂起;除非给出了timeout(秒),否则一直阻塞,用于判断线程是否终止
import threading
from time import sleep, ctime
loops = [4, 2]

def loop(nloop, nsec):
    print('start loop', nloop, 'at:', ctime())
    sleep(nsec)
    print('loop', nloop, 'done at:', ctime())

def main():
    print('starting at:', ctime())
    threads = []
    nloops = range(len(loops))

    for i in nloops:
        t = threading.Thread(target=loop, args = (i, loops[i]))
        threads.append(t)
    
    for i in nloops:
        threads[i].start()

    for i in nloops:
        threads[i].join()

    print('all DONE at:', ctime())

if __name__ == '__main__':
    main()
starting at: Sun Mar 21 21:29:39 2021
start loop 0 at: Sun Mar 21 21:29:39 2021
start loop 1 at: Sun Mar 21 21:29:39 2021
loop 1 done at: Sun Mar 21 21:29:41 2021
loop 0 done at: Sun Mar 21 21:29:43 2021
all DONE at: Sun Mar 21 21:29:43 2021

这里是创建Thread的实例,将函数和参数传递给它。

import threading
from time import sleep, ctime
loops = [4, 2]

class ThreadFunc:
    def __init__(self, func, args, name = ''):
        self.func = func
        self.args = args
        self.name = name

    def __call__(self):
        self.func(*self.args)

def loop(nloop, nsec):
    print('start loop', nloop, 'at:', ctime())
    sleep(nsec)
    print('loop', nloop, 'done at:', ctime())

def main():
    print('starting at:', ctime())
    threads = []
    nloops = range(len(loops))

    for i in nloops:
        t = threading.Thread(target=ThreadFunc(loop, (i, loops[i]), loop.__name__))
        threads.append(t)
    
    for i in nloops:
        threads[i].start()

    for i in nloops:
        threads[i].join()

    print('all DONE at:', ctime())

if __name__ == '__main__':
    main()

这是传入一个可调用的实例。

import threading
from time import sleep, ctime

loops = (4, 2)

class MyThread(threading.Thread):
    def __init__(self, func, args, name = ''):
        threading.Thread.__init__(self)
        self.name = name
        self.func = func
        self.args = args
    
    def run(self):
        self.func(*self.args)

def loop(nloop, nsec):
    print('start loop', nloop, 'at:', ctime())
    sleep(nsec)
    print('loop', nloop, 'done at:', ctime())

def main():
    print('starting at:', ctime())
    threads = []
    nloops = range(len(loops))
    
    for i in nloops:
        t = MyThread(loop, (i, loops[i]), loop.__name__)
        threads.append(t)

    for i in nloops:
        threads[i].start()

    for i in nloops:
        threads[i].join()

    print('all DONE at:', ctime())

if __name__ == '__main__':
    main()

这是创建一个Thread的子类,在子类的run函数定义这个线程做什么。

from atexit import register
@register
def fun():
	pass

这是一个装饰器,fun()会在程序退出之前执行,因此不必设置join。

  1. 2to3工具

找到2to3.py。。。。。。

  1. 同步问题
  • 锁机制

当多个线程争夺锁时,允许第一个获得锁的线程进入临界区,并执行代码。之后到达的线程都会被阻塞,知道第一个线程执行结束,退出临界区,并释放锁。此时其他等待的线程可以获得锁并进入临界区,不过这些阻塞的线程谁先获得锁是不确定的(不是先到先得)。

print('%s' % (a or b))

先创建一个锁对象
当需要使用共享资源时,先lock.acquire(),使用完之后,lock.release()。也可以with lock,然后使用共享资源,无需释放。

  • 信号量
from atexit import register
from random import randrange
from threading import Thread, BoundedSemaphore, Lock
from time import sleep, ctime

lock = Lock()
MAX = 5
candytray = BoundedSemaphore(MAX)

def refill():

    lock.acquire()
    print('Refilling candy...')
    try:
        candytray.release()
    except ValueError:
        print('full, skipping')
    else:
        print('OK')
    lock.release()

def buy():
    lock.acquire()
    print('Buying candy...')
    if candytray.acquire(False):
        print('OK')
    else:
        print('empty, skipping')
    lock.release()

def producer(loops):
    for i in range(loops):
        refill()
        sleep(randrange(3))

def consumer(loops):
    for i in range(loops):
        buy()
        sleep(randrange(3))

def _main():
    print('starting at:', ctime())
    nloops = randrange(2, 6)
    print('The candy machine (full with %d bars)!' % MAX)
    Thread(target=consumer, args=(randrange(nloops,nloops+MAX+2),)).start()
    Thread(target=producer,args=(nloops,)).start()

@register
def _atexit():
    print('all done at:', ctime())

if __name__ == '__main__':
    _main()

信号量的P,V操作在python中也是acquire()和release()。BoundedSemaphore保证资源量不会超过初始值。

  1. 生产者与消费者和queue模块
from random import randint
from time import sleep
from queue import Queue
from myThread import MyThread

def writeQ(queue):
    print('producing object for Q...')
    queue.put('xxx',1)				
    print('size now', queue.qsize())

def readQ(queue):
    val = queue.get(1)
    print('consumed object from Q... size now', queue.qsize())

def writer(queue, loops):
    for i in range(loops):
        writeQ(queue)
        sleep(randint(1, 3))

def reader(queue, loops):
    for i in range(loops):
        readQ(queue)
        sleep(randint(2, 5))

funcs = [writer, reader]
nfuncs = range(len(funcs))

def main():
    nloops = randint(2, 5)
    q = Queue(32)

    threads = []
    for i in nfuncs:
        
        t = MyThread(funcs[i], (q, nloops), funcs[i].__name__)
        threads.append(t)

    for i in nfuncs:
        threads[i].start()

    for i in nfuncs:
        threads[i].join()

    print('all Done')

if __name__ == '__main__':
    main()

queue.put(item, block = true, timeout),block如果为True,且timeout = none,则一直阻塞到队列中有元素为止。queue.get(block = true, timeout)取出一个元素。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值