Python -- 多线程

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容

  • 一文读懂Python多线程 1、线程和进程 计算机的核心是CPU,它承担了所有的计算任务。它就像一座工厂,时刻在运...
    星丶雲阅读 1,380评论 0 4
  • Python 多线程 多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序...
    今早上阅读 337评论 0 0
  • 免费Python课程:阿里云大学——开发者课堂 Python中使用线程有两种方式:函数或者用类来包装线程对象。 函...
    开发者学习指南阅读 197评论 0 0
  • 多线程基础概念 并行与并发 并行:同时处理多个任务,必须在多核环境下 一段时间内同时处理多个任务,单核也可以并发 ...
    职场亮哥阅读 585评论 0 0
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,401评论 16 21