您的位置:首页 > 编程语言 > Python开发

python核心编程学习笔记-2016-08-27-01-多线程编程

2016-08-27 19:21 363 查看
        18.2 线程和进程

        进程是程序的一次执行,拥有自己的地址空间、内存、数据栈及其他记录其运行轨迹的辅助数据。只能使用进程间通讯(IPC),而不能共享信息。

        线程,与进程有些相似。但所有线程都运行在同一个进程中。它有开始、顺序执行和结束三部分,也可能被中断、挂起。线程之间共享同一片数据空间。线程一般是并发执行的。

        18.3 python、线程和全局解释器锁

         全局解时器锁(GIL),对这个概念不是很理解。但它能保证同一时刻只有一个线程在运行。

         在多线程环境中,python虚拟机执行方式:

         1. 设置GIL;

         2. 切换到一个线程去运行;

         3. 运行:

                a. 指定数量的字节码的指令,或者

                b. 线程主动让出控制(可以调用time.sleep(0))

         4. 把线程设置成睡眠状态;

         5. 解锁GIL;

         6. 重复上述过程。

         之后是本章的所有例子。

onethr.py

#-*-coding: utf-8-*-

# 程序执行顺序是loop0-->loop1,在print "loop 0 done at:", ctime()执行完后,才开始执行loop1()。

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()
sleep(2)
print "loop 1 done at:", ctime()

def main():
print "starting at:", ctime()
loop0()
loop1()
print "all DONE at:", ctime()

if __name__ == "__main__":
main()


mtsleep1.py

#-*-coding: utf-8-*-

# 显然loop0和loop1同时运行,loop1先结束,然后loop0结束,之后再执行接下来的语句。
# sleep(6)正是让主线程休眠6s,而在这6s内,两个子线程分别将loop0()和loop1()运行完。

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()
sleep(2)
print "loop 1 done at:", ctime()

def main():
print "starting at:", ctime()
thread.start_new_thread(loop0,()) # 创建一个线程,并在其中运行函数loop0
thread.start_new_thread(loop1,()) # 创建另一个线程,并在其中运行函数loop1
sleep(6) # 不可缺少,由于主线程并没有停下来,它不会等两个子线程运行完后,再继续运行之后的代码。如果将这一句注释掉,程序只会运行main(),不执行loop0和loop1两个函数
print "all DONE at:", ctime()

if __name__ == "__main__":
main()
mtsleep2.py

#-*-coding: utf-8-*-

import thread
from time import sleep, ctime

loops = [4, 2] # 每个loop的sleep时间

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()
mtsleep3.py

#-*-coding: utf-8-*-

import threading
from time import sleep, ctime

loops = [4, 2] # 每个loop的sleep时间

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])) # Thread对象,也是传入一个函数对象和相应的参数作为参数,但在这一步,线程并未开始。
threads.append(t)

for i in nloops:
threads[i].start() # 线程开始

for i in nloops:
threads[i].join() # join()函数允许主线程等待子线程运行完毕,无需再管理锁

print "all DONE at:", ctime()

if __name__ == "__main__":
main()
mtsleep4.py

#-*-coding: utf-8-*-

import threading
from time import sleep, ctime

loops = [4, 2]

class ThreadFunc(object):

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

def __call__(self):
apply(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__)) # Thread对象传入可调用的类对象作为参数,实际是可调用实例作为参数?
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()
mtsleep5.py

#-*-coding: utf-8-*-

import threading
from time import sleep, ctime

loops = (4, 2)

class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self) # 先调用基类threading.Thread的构造器
self.name = name
self.func = func
self.args = args

def run(self): # 定义线程的功能,在派生子类中被重写,在本例中就是运行loop()函数。
apply(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()
myThread.py

#-*-coding: utf-8-*-

import threading
from time import sleep, ctime

loops = (4, 2)

class MyThread(threading.Thread):
def __init__(self, func, args, name=''):
threading.Thread.__init__(self) # 先调用基类threading.Thread的构造器
self.name = name
self.func = func
self.args = args

def getResult(self):
return self.res

def run(self): # 定义线程的功能,在派生子类中被重写,在本例中就是运行loop()函数。
print "starting", self.name, "at:", ctime()
self.res = self.func(*self.args)
print self.name, "finished at:", ctime()
mtfacfib.py

#-*-coding: utf-8-*-

# 先单线程运行fib, fac, sum,再多线程同时运行这三个函数

from myThread import MyThread
from time import ctime, sleep

def fib(x):
sleep(0.005)
if x < 2: return 1
return (fib(x-2) + fib(x-1))

def fac(x):
sleep(0.1)
if x < 2: return 1
return (x * fac(x-1))

def sum(x):
sleep(0.1)
if x < 2: return 1
return (x + sum(x-1))

funcs = [fib, fac, sum]
n = 12

def main():
nfuncs = range(len(funcs))

print "*** SINGLE THREAD"
for i in nfuncs:
print "starting", funcs[i].__name__, 'at:', ctime()
print funcs[i](n)
print funcs[i].__name__, "finished at:", ctime()

pri
4000
nt "\n*** MULTIPLE THREADS"
threads = []
for i in nfuncs:
t = MyThread(funcs[i], (n,), funcs[i].__name__)
threads.append(t)

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

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

print "all DONE"

if __name__ == "__main__":
main()
prodcons.py

#-*-coding: utf-8-*-

# 创建一个队列,让生产者(线程)把新生产的货物放进去供消费者(线程)使用。

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 %d" % queue.qsize()

def readQ(queue): # 消耗队列中的一个对象
val = queue.get(1)
print "consumed object from Q... size now %d" % queue.qsize()

def writer(queue, loops): # 把对象放入一个队列,等待随机秒,重复loops次
for i in range(loops):
writeQ(queue)
sleep(randint(1, 3)) # writer睡眠时间要短

def reader(queue, loops): # 从队列中消耗一个对象,等待随机秒,重复loops次
for i in range(loops):
readQ(queue)
sleep(randint(2, 5)) # reader睡眠时间要长,尽量保证reader不从空队列中消耗对象

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()
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  python 编程