Python -- 多线程

2020-07-11  本文已影响0人  墨凌风起

--coding:utf-8--

2 python实现线程的方式

'''
1.函数方式(涉及_thread模块)
2.用类包装线程对象(涉及threading模块)
'''

2.1函数方式实现多线程

'''
1.调用_thread模块的start_new_thread()函数创建并启动新线程
语法:_thread.start_new_thread(function,args[,kwargs])
function:线程函数
args:传递给线程函数的参数,必须是tuple类型
kwargs:可选参数
'''
'''
import _thread
import time
def workThread(threadName,delay):
print('[启动]>>>{0}'.format(threadName))
counter = 0 #计数器
for i in range(delay):
counter += 1
time.sleep(1)
pass
print('[停止]>>>{0}'.format(threadName))
pass

if name == 'main':
_thread.start_new_thread(workThread,('thread-1',3))
_thread.start_new_thread(workThread,('thread-2',5))
for i in range(4):
print('mainThread正在执行')
time.sleep(1)
pass
print('>>>主线程mainThread停止\a')
print('-' * 50)

'''
'''
备注:线程结束一般依靠线程函数的自然结束,也可在线程中调用thread.exit(),抛出SystemExit exception 达到退出线程的目的
'''

2.2模块实现方式

'''
python通过两个标准库_thread和threading提供线程支持
_thread提供低级别的,原始的线程以及一个简单的锁
threading模块提供其他方法:
1.threading.currentThread():返回当前线程变量
2.threading.enumerate():返回一个包含正在运行线程的list,正在运行线程启动后,结束前,不包括启动前和终止后的线程
3.threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

除此之外,线程模块提供threading.Thread类来处理线程,threading.Thread提供如下函数
1.run():表示线程活动的方法
2.start():启动线程活动
3.join([time]):等待至线程中止,这阻塞调用线程直至线程的join()方法被调用中止-正常退出或者抛出未处理的异常-或者是可选
4.isAlive():返回线程是否是活动的
5.getName():返回线程名
6.setName():设置线程名

语法:
import threading

创建线程类

class 线程类名称(threading.Thread):

def __init__(self,参数1,...,参数N):
    #调用父类构造方法
    threading.thread.__init__(self)
    ...
#重写run(),线程启动后的调用
def run():
    ...

线程对象 = 线程类名称()
线程对象.run() #启动线程
'''
'''
import threading
import time
exitFlag = 0 #创建推出标志位变量

def outputTime(threadName,delay,counter):
while counter:
if exitFlag:
threading.Thread.exit()
time.sleep(delay)
print('%s:%s' % (threadName,time.ctime(time.time())))
counter -= 1
pass
pass

class MyThread(threading.Thread):
"""docstring for MyThread"""
def init(self, threadID,name,counter):
threading.Thread.init(self)
self.threadID = threadID
self.name = name
self.counter = counter

def run(self):
    print('启动>' + self.name)
    outputTime(self.name,self.counter,5)
    print('结束>' + self.name)
    pass

if name == 'main':
print('mainThread主线程启动.....')
thread1 = MyThread(1,'thread-11',1)
thread2 = MyThread(2,'thread-22',1)
thread1.run()
thread2.run()
print('mainThread主线程结束')
'''

3.线程同步

'''
线程有五个状态,状态切换如下
启动 调度 结束
新建 就绪 运行 死亡
| 阻塞条件
阻塞

所线程在执行时为随机模式,不可控,要求执行顺序可控就得用线程同步
Python 线程同步技术的解决方案:锁同步和条件变量同步

3.1创建线程锁的语法:
线程锁对象 = Threading.Lock
锁定:线程锁对象.acquire()
解除锁定:线程锁对象.release()

使用场景:
def run(self):
线程锁对象.acquire()
...线程执行语句...
线程锁对象.release()

3.2条件变量同步

python 提供的Condition对象提供了对复杂线程同步问题的支持
Condition被称为条件变量,除了提供Lock类似的acquire和release方法,还提供wait和notify
工作原理:
线程首先acquire一个条件变量,然后判断一些条件,不满足wait,满足进行处理改变条件后,通过notify方法通知其他线程,其他处于wait的线程接到通知会重新判断条件,重复这一过程,从而解决复杂的同步问题
'''

示例:生产者和消费者

'''
生产者消费者问题(有限缓冲问题),是一个多线程同步的经典案例,该问题描述两个共享固定大小缓存的线程--即所谓的‘生产者‘和’消费者‘在实际运行时会发生的问题
生产者作用时生成一定量的数据放到缓冲区,重复此过程
消费者在缓冲区消耗这些数据
该问题的【关键】保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区空时消耗数据
任务说明:
1.创建一个共享区,容量是10
2.两个生产者,随机时间单位产生1件商品放入共享区,count + 1,共享区满,生产者停止放入共享区,线程进入block阻塞状态,等待消费者线程唤醒
3.五个消费者,随机时间单位产生从共享区取1件商品,count - 1,共享区空,消费者停止从共享区获取,线程进入block阻塞状态,等待生产者线程唤醒
'''
import threading
import time
import random #随机模块

使用共享区模拟变量

count= 0

创建条件对象

condition = threading.Condition()

生产者线程类

class Producer(threading.Thread):
def init(self,threadName):
threading.Thread.init(self)
self.threadName = threadName

def run(self):
    global count #引用全局共享变量count
    while True:
        #使用条件变量后去锁并速定
        if condition.acquire():
            #判断共享变量是否达到上限(已满)
            if count >= 10:
                print('共享区已满,生产者Producer线程进入阻塞block状态,停止放入!')
                #当前线程进入阻塞状态
                condition.wait()
            else:
                count += 1 #共享变量自增1
                print(time.ctime() + ' ' + self.threadName + '生产了1件商品放入共享区,共享区商品总计个数:{0}'.format(count))
                condition.notify() #唤醒其他阻塞线程
            condition.release()
            time.sleep(random.randrange(10)/5) #随机休眠N秒

消费者线程

class Customer(threading.Thread):
def init(self, threadName):
threading.Thread.init(self)
self.threadName = threadName

def run(self):
    global count #引用全局共享变量count
    while True:
        #使用条件变量后去锁并速定
        if condition.acquire():
            #判断共享变量是否达到上限(已满)
            if count < 1:
                print('共享区已空,消费者Customer线程进入阻塞block状态,停止获取!')
                #当前线程进入阻塞状态
                condition.wait()
            else:
                count -= 1 #共享变量自减1
                print(time.ctime() + ' ' + self.threadName + '消费了1件商品,共享区商品总计个数:' + str(count))
                condition.notify() #唤醒其他阻塞线程
            condition.release()
            time.sleep(random.randrange(10)) #随机休眠N秒

if name == 'main':
for i in range(2):
p = Producer('[生产者-' + str(i + 1) + ']')
p.start()

for i in range(5):
    c = Producer('[消费者-' + str(i + 1) + ']')
    c.start()
上一篇下一篇

猜你喜欢

热点阅读