博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python基础---线程
阅读量:6406 次
发布时间:2019-06-23

本文共 3775 字,大约阅读时间需要 12 分钟。

调用方式

python的线程调用有两种方式。一种是直接调用,一种是继承式调用

直接调用

import threading,time#方法一def run(n):    print(n)    time.sleep(2)t1 = threading.Thread(target=run,args=("t1",))t2 = threading.Thread(target=run,args=("t2",))t1.start()t2.start()
使用类的方法调用
#方法二(使用类的方法)import threading,timeclass MyThread(threading.Thread):    def __init__(self,n):        super(MyThread,self).__init__()        self.n = n    def run(self):     #函数名必须为run        print(self.n)        time.sleep(2)t1 = MyThread(1)t2 = MyThread(2)t1.start()t2.start()

join和Daemon

join()等待线程结束后再往后继续运行

Daemon()守护线程

使用setDaemon(True)那么主线程不会等待子线程结束才结束,主线程结束后子线程也会直接结束,必须要在start之前设置否则会报错

python中默认为setDaemon(False),主线程结束了子线程依然会执行直到完毕。

join例子:

import threading,timeclass MyThread(threading.Thread):    def __init__(self,n):        super(MyThread,self).__init__()        self.n = n    def run(self):     #函数名必须为run        print(self.n)        time.sleep(2)        print('end')t1 = MyThread('t1')t2 = MyThread('t2')t1.start()t1.join()t2.start()t2.join()
结果

setDaemon()例子

import threading,timeclass MyThread(threading.Thread):    def __init__(self,n):        super(MyThread,self).__init__()        self.n = n    def run(self):     #函数名必须为run        print(self.n)        time.sleep(2)        print('end')t1 = MyThread('t1')t2 = MyThread('t2')t1.setDaemon(True)t2.setDaemon(True)t1.start()t2.start()

结果

线程锁

子线程可以共享父线程的内存空间,当存在多个子线程需要同时修改一个数据的时候就可能出现问题
假设两个子线程执行的操作都是num+1,由于线程是同时执行的,第一个子线程先取num = 1 ,第二个线程有取出num依然为1,线程一结束后num更改为2,随之线程二结束num依然被改为2,就与我们的目标出现冲突,这个时候就需要用到线程锁了,当线程一访问num的时候线程二是无法访问num的,线程一结束后释放num线程二才能访问num,这就使得num的结果不会产生冲突了。
#线程锁示例import threadingnum = 0t_objs = []lock = threading.Lock()def run():    lock.acquire()  #加锁    global num      #声明全局变量    num += 1        #执行加一操作    lock.release()  #释放锁for i in range(500):    t = threading.Thread(target=run)    t.start()    t_objs.append(t)for t in t_objs:    #等待所有线程结束    t.join()print(num)
递归锁则是在一个锁里面又嵌套另外一个线程锁
#递归锁import threadingdef run1():    lock.acquire()    global num    num += 1    lock.release()    return numdef run2():    lock.acquire()    global num2    num2 += 1    lock.release()    return num2def run3():    lock.acquire()    res = run1()    res2 = run2()    lock.release()    print(res, res2)if __name__ == '__main__':    num, num2 = 0, 0    lock = threading.RLock()    for i in range(10):        t = threading.Thread(target=run3)        t.start()
结果

信号量(Semaphore)

线程锁每次只允许一个线程操作数据,Semaphore则可同时允许多个线程操作,当达到允许的最大值的时候后面的则需要等待,前面的线程执行完毕后才可执行,因此操作同一个数据的时候依然有可能出错
#信号量import threading,timedef run(num):    semaphore.acquire()    time.sleep(1)    print(num)    semaphore.release()semaphore = threading.BoundedSemaphore(3) #最多运行三个线程for i in range(10):    t = threading.Thread(target=run,args=(i,))    t.start()

事件(Event)

Event默认内置了一个标志,初始值为False
event总共就四中方法:set()、clear()、wait()、is_set()
set()设置标志位为True
clear()设置标志位为False
wait()等待标志位设为True
is_set()判断标志位是否被设为True
已红绿灯为例说明,首先写出交通灯,event.clear()相当于红灯,event.set()相当于绿灯,红灯为5秒绿灯也为5秒,用count来计数,当count超过10的时候重置count,这样红绿灯就能以5秒为间隔循环运行
import time,threadingevent = threading.Event()def light():    count = 0    while True:        if count >= 5 and count < 10:            event.clear()     #相当于红灯了            print("red light please wait...")        elif count > 10 :            event.set()       #相当于绿灯            count = 0                else:            print("go go go ...")        time.sleep(1)        count += 1
再来写car
def car():    while True:        if event.is_set():  #判断event是否被set,相当于检测是否为绿灯            print('run...')            time.sleep(1)        else:            print('waiting for green light..')            event.wait()            print('green light is on go...')
运行
l = threading.Thread(target=light)c = threading.Thread(target=car)l.start()c.start()
最终的结果

转载于:https://www.cnblogs.com/FanMLei/p/10501032.html

你可能感兴趣的文章
Android 滑动效果入门篇(二)—— Gallery
查看>>
Revit二次开发示例:DesignOptions
查看>>
Entity Framework 系统约定配置
查看>>
优秀设计:纹理在网页设计中的20个应用示例
查看>>
C++ 关键字 explicit, export, mutable
查看>>
生成指定范围的一组随机数并求平均值
查看>>
android语音识别方法
查看>>
File Operations in Android NDK(转)
查看>>
如何将kux格式的视频转换成我们常用的MP4格式
查看>>
[sublime系列文章] sublime text 3插件配置说明
查看>>
学习 PixiJS — 碰撞检测
查看>>
Vue 基础篇
查看>>
JavaScript:函数防抖与函数节流
查看>>
关于区间贪心的补全
查看>>
架构设计步骤
查看>>
自定义元素探秘及构建可复用组件最佳实践
查看>>
区块链是一个公共数据库,要放在一个块内
查看>>
Jenkins 用户文档(目录)
查看>>
系统常见指标
查看>>
使用crond构建linux定时任务及日志查看
查看>>