python多线程threading之阻塞线程(join)线程同步和守护线程(setDaemon(True))实例详解

 

一、多线程(主线程和子线程同时执行)

1、主线程是程序本身,看不到的,主线程和子线程没有依赖关系,同步执行的,若主线程先执行完,会等子线程执行完毕,程序结束

2、启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行run()

3、threading.currentThread(): 返回当前的线程变量<Thread(Thread-1, started 8056)>、<_MainThread(MainThread, started 14400)>

threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程;

threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

run(): 用以表示线程活动的方法

start():启动线程活动

join(timeout): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生;

sAlive(): 返回线程是否活动的

getName(): 返回线程名;setName(): 设置线程名

4、多线程实例

#函数式多线程
import time,threading
def learnEnglish():
    print('%s 橙子在学习英语 %s'%(threading.currentThread(),time.ctime()))
def learnPython(name):
    print('%s %s在学习英语 %s'%(threading.currentThread(),name,time.ctime()))
def learnC(name,course):
    print('%s %s在学习%s %s'%(threading.currentThread(),name,course,time.ctime()))
start_time=time.time()
threads=[]# 创建线程数组
thread1=threading.Thread(target=learnEnglish)#创建线程
thread2=threading.Thread(target=learnPython,args=('橙汁',))
thread3=threading.Thread(target=learnC,args=('柠檬','C',))
thread4=threading.Thread(target=learnC,kwargs={"name":"王荔","course":"测试"})
threads.append(thread1)#将线程1添加到线程数组
threads.append(thread2)
threads.append(thread3)
threads.append(thread4)
for i in threads:
    i.start()#启动线程
run_times=(time.time()-start_time)
print('%s %s'%(threading.currentThread(),time.ctime()))
print('主线程和子线程运行时间共:%s'%run_times)


C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
<Thread(Thread-1, started 5664)> 橙子在学习英语 Thu Mar 14 13:12:25 2019
<Thread(Thread-2, started 6964)> 橙汁在学习英语 Thu Mar 14 13:12:25 2019
<Thread(Thread-3, started 17908)> 柠檬在学习C Thu Mar 14 13:12:25 2019
<Thread(Thread-4, started 17816)> 王荔在学习测试 Thu Mar 14 13:12:25 2019
<_MainThread(MainThread, started 12276)> Thu Mar 14 13:12:25 2019
主线程和子线程运行时间共:0.0009965896606445312

Process finished with exit code 0
#多线程threading之封装
import threading,time
class MyThread(threading.Thread):#继承父类threading.Thread
    def __init__(self,name,people):
        '''重写threading.Thread初始化内容'''
        super(MyThread,self).__init__()
        self.threadName=name
        self.people=people
    def run(self):# 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        print('开始线程%s %s'%(self.threadName,time.ctime()))
        print('结束线程%s %s'%(self.threadName,time.ctime()))
start_time=time.time()
print('开始主线程%s'%time.ctime())
thread1=MyThread('Thread-1','王荔')
thread2=MyThread('Thread-2','橙子')
thread1.start()
thread2.start()
print('退出主线程%s'%time.ctime())
run_times=(time.time()-start_time)
print('运行时间%s'%run_times)


C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
开始主线程Thu Mar 14 13:16:10 2019
开始线程Thread-1 Thu Mar 14 13:16:10 2019
结束线程Thread-1 Thu Mar 14 13:16:10 2019
开始线程Thread-2 Thu Mar 14 13:16:10 2019
退出主线程Thu Mar 14 13:16:10 2019
运行时间0.0009996891021728516
结束线程Thread-2 Thu Mar 14 13:16:10 2019

Process finished with exit code 0

-----可以看到主线程和子线程是同时运行的,主线程运行完,子线程可能还在运行;子线程运行完,主线程可能还在运行

 

二、多线程之线程阻塞,子线程.join()(设置在start之后,等所有阻塞线程运行完,再运行主线程)

1、阻塞主线程必须在start()方法后执行,t1.join()等线程1运行完,t2.join()等线程2运行完,再运行主线程

2、如果想让主线程等待子线程结束后再运行,就需用到【子线程.join()】,此方法是在start后(与setDaemon相反)

3、join(timeout)此方法有个timeout参数,是线程超时时间设置

4、阻塞线程和非阻塞线程实例

#非阻塞线程,主线程休眠1s,子线程休眠3s
时间未统计到子线程,只统计到主线程的,说明主线程和子线程是同步执行的,且主线程执行完了,子线程还在执行

import threading,time
class MyThread(threading.Thread):#继承父类threading.Thread
    def __init__(self,name,people):
        '''重写threading.Thread初始化内容'''
        super(MyThread,self).__init__()
        self.threadName=name
        self.people=people
    def run(self):# 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        print('开始线程%s %s'%(self.threadName,time.ctime()))
        time.sleep(3)
        print('结束线程%s %s'%(self.threadName,time.ctime()))
start_time=time.time()
print('开始主线程%s'%time.ctime())
thread1=MyThread('Thread-1','王荔')
thread2=MyThread('Thread-2','橙子')
thread1.start()
thread2.start()
#thread1.join()
#thread2.join()
print('退出主线程%s'%time.ctime())
time.sleep(1) 
run_times=(time.time()-start_time)


C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
开始主线程Thu Mar 14 13:30:07 2019
开始线程Thread-1 Thu Mar 14 13:30:07 2019
开始线程Thread-2 Thu Mar 14 13:30:07 2019
退出主线程Thu Mar 14 13:30:07 2019
运行时间1.0023198127746582
结束线程Thread-1 Thu Mar 14 13:30:10 2019
结束线程Thread-2 Thu Mar 14 13:30:10 2019

Process finished with exit code 0
#阻塞线程1、阻塞线程2,主线程休眠1s,线程1和线程2休眠3s
主线程会等线程1和线程2执行完,才会继续执行主线程,统计时间为主线程1s+子线程3s=4s
import threading,time
class MyThread(threading.Thread):#继承父类threading.Thread
    def __init__(self,name,people):
        '''重写threading.Thread初始化内容'''
        super(MyThread,self).__init__()
        self.threadName=name
        self.people=people
    def run(self):# 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        print('开始线程%s %s'%(self.threadName,time.ctime()))
        time.sleep(3)
        print('结束线程%s %s'%(self.threadName,time.ctime()))
start_time=time.time()
print('开始主线程%s'%time.ctime())
thread1=MyThread('Thread-1','王荔')
thread2=MyThread('Thread-2','橙子')
thread1.start()
thread2.start()
thread1.join()#阻塞线程1
thread2.join()#阻塞线程2
time.sleep(1)
print('退出主线程%s'%time.ctime())
run_times=(time.time()-start_time)
print('运行时间%s'%run_times)

C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
开始主线程Thu Mar 14 13:35:29 2019
开始线程Thread-1 Thu Mar 14 13:35:29 2019
开始线程Thread-2 Thu Mar 14 13:35:29 2019
结束线程Thread-1 Thu Mar 14 13:35:32 2019
结束线程Thread-2 Thu Mar 14 13:35:32 2019
退出主线程Thu Mar 14 13:35:33 2019
运行时间4.004500389099121

Process finished with exit code 0
#阻塞线程实例

# coding=utf-8
import threading
import time

def chiHuoGuo(people):
    print("%s 吃火锅的小伙伴-羊肉:%s" % (time.ctime(),people))
    time.sleep(1)
    print("%s 吃火锅的小伙伴-鱼丸:%s" % (time.ctime(),people))


class myThread (threading.Thread):   # 继承父类threading.Thread
    def __init__(self, people, name):
        '''重写threading.Thread初始化内容'''
        threading.Thread.__init__(self)
        self.threadName = name
        self.people = people

    def run(self):   # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        '''重写run方法'''
        print("开始线程: " + self.threadName)

        chiHuoGuo(self.people)     # 执行任务
        print("qq交流群:226296743")
        print("结束线程: " + self.name)

print("yoyo请小伙伴开始吃火锅:!!!")

# 创建新线程
thread1 = myThread("xiaoming", "Thread-1")
thread2 = myThread("xiaowang", "Thread-2")

# 开启线程
thread1.start()
thread2.start()

# 阻塞主线程,等子线程结束
thread1.join()
thread2.join()

time.sleep(0.1)
print("退出主线程:吃火锅结束,结账走人")


C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
yoyo请小伙伴开始吃火锅:!!!
开始线程: Thread-1
Thu Mar 14 13:41:10 2019 吃火锅的小伙伴-羊肉:xiaoming
开始线程: Thread-2
Thu Mar 14 13:41:10 2019 吃火锅的小伙伴-羊肉:xiaowang
Thu Mar 14 13:41:11 2019 吃火锅的小伙伴-鱼丸:xiaowang
qq交流群:226296743
结束线程: Thread-2
Thu Mar 14 13:41:11 2019 吃火锅的小伙伴-鱼丸:xiaoming
qq交流群:226296743
结束线程: Thread-1
退出主线程:吃火锅结束,结账走人

Process finished with exit code 0

三、守护线程(设置在start之前,设置子线程A为守护线程,主线程所在的进程内所有非守护线程统统运行完毕 ,无论子线程A有没有结束,程序都结束)

1、主线程退出时,不等那些子线程完成,那就设置子线程为守护线程thread1.setDaemon(True)

2、设置一个线程为守护线程,就表示你在说这个线程不重要,在进程退出时,不用等待这个线程退出

3、程序在等待子线程结束,才退出,不需要设置线程守护,或者显示调用thread1.setDaemon(False)

4、主线程是非守护线程,只要还存在一个非守护线程,程序就不会退出。

5、守护线程必须在start()方法调用之前设置,如果不设置为守护线程,程序会被无限挂起

6、当有多个子线程时,守护线程就会等待所有的子线程运行完毕后,守护线程才会挂掉(这一点和主线程是一样的,都是等待所有的子线程运行完毕后才会挂掉)。

7、调用线程对象的方法setDaemon(true),则可以将其设置为守护线程。在python中建议使用的是thread.demon = true 使用这个方法可以检测数据合法性

8、setDaemon(True)此方法里面参数设置为True才会生效

9、对于主线程运行完毕,指的是主线程所在的进程内所有非守护线程统统都运行完毕,主线程才算运行完毕

10、守护线程实例

#设置线程1和线程2为守护线程
因为程序没有其他非守护线程,所以当主线程运行完,不等线程1和线程2,就直接结束

import threading,time
class MyThread(threading.Thread):#继承父类threading.Thread
    def __init__(self,name,people):
        '''重写threading.Thread初始化内容'''
        super(MyThread,self).__init__()
        self.threadName=name
        self.people=people
    def run(self):# 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        time.sleep(3)
        print('开始线程%s %s'%(self.threadName,time.ctime()))
        print('结束线程%s %s'%(self.threadName,time.ctime()))
start_time=time.time()
print('开始主线程%s'%time.ctime())
thread1=MyThread('Thread-1','王荔')
thread2=MyThread('Thread-2','橙子')
thread1.setDaemon(True)#设置为守护线程
thread2.setDaemon(True)#设置为守护线程
thread1.start()
thread2.start()
print('退出主线程%s'%time.ctime())
run_times=(time.time()-start_time)
print('运行时间%s'%run_times)

C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
开始主线程Thu Mar 14 13:59:09 2019
退出主线程Thu Mar 14 13:59:09 2019
运行时间0.0009975433349609375

Process finished with exit code 0
#将线程2设置为守护线程
当线程1和主线程运行完,程序立即结束;故会存在2种结果:
当线程1先结束,就不会执行线程2结束
当线程2先结束,就会出执行线程2结束

import threading,time
class MyThread(threading.Thread):#继承父类threading.Thread
    def __init__(self,name,people):
        '''重写threading.Thread初始化内容'''
        super(MyThread,self).__init__()
        self.threadName=name
        self.people=people
    def run(self):# 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        print('开始线程%s %s'%(self.threadName,time.ctime()))
        time.sleep(3)
        print('结束线程%s %s'%(self.threadName,time.ctime()))
start_time=time.time()
print('开始主线程%s'%time.ctime())
thread1=MyThread('Thread-1','王荔')
thread2=MyThread('Thread-2','橙子')
#thread1.setDaemon(True)#设置为守护线程
thread2.setDaemon(True)#设置为守护线程
thread2.start()
thread1.start()
print('退出主线程%s'%time.ctime())
run_times=(time.time()-start_time)
print('运行时间%s'%run_times)


C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
开始主线程Thu Mar 14 14:11:07 2019
开始线程Thread-2 Thu Mar 14 14:11:07 2019
开始线程Thread-1 Thu Mar 14 14:11:07 2019
退出主线程Thu Mar 14 14:11:07 2019
运行时间0.0009958744049072266
结束线程Thread-2 Thu Mar 14 14:11:10 2019
结束线程Thread-1 Thu Mar 14 14:11:10 2019

Process finished with exit code 0


C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
开始主线程Thu Mar 14 14:13:03 2019
开始线程Thread-2 Thu Mar 14 14:13:03 2019
开始线程Thread-1 Thu Mar 14 14:13:03 2019
退出主线程Thu Mar 14 14:13:03 2019
运行时间0.0009908676147460938
结束线程Thread-1 Thu Mar 14 14:13:06 2019

Process finished with exit code 0
#守护线程实例

# coding=utf-8
import threading
import time

def chiHuoGuo(people):
    print("%s 吃火锅的小伙伴-羊肉:%s" % (time.ctime(),people))
    time.sleep(1)
    print("%s 吃火锅的小伙伴-鱼丸:%s" % (time.ctime(),people))


class myThread (threading.Thread):   # 继承父类threading.Thread
    def __init__(self, people, name):
        '''重写threading.Thread初始化内容'''
        threading.Thread.__init__(self)
        self.threadName = name
        self.people = people

    def run(self):   # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数
        '''重写run方法'''
        print("开始线程: " + self.threadName)

        chiHuoGuo(self.people)     # 执行任务
        print("qq交流群:226296743")
        print("结束线程: " + self.name)

print("yoyo请小伙伴开始吃火锅:!!!")

# 创建新线程
thread1 = myThread("xiaoming", "Thread-1")
thread2 = myThread("xiaowang", "Thread-2")

# 守护线程setDaemon(True)
thread1.setDaemon(True)       # 必须在start之前
thread2.setDaemon(True)

# 开启线程
thread1.start()
thread2.start()

time.sleep(0.1)
print("退出主线程:吃火锅结束,结账走人")

C:\Users\wangli\PycharmProjects\AutoMation\venv\Scripts\python.exe C:/Users/wangli/PycharmProjects/AutoMation/case/test.py
yoyo请小伙伴开始吃火锅:!!!
开始线程: Thread-1
Thu Mar 14 14:22:20 2019 吃火锅的小伙伴-羊肉:xiaoming
开始线程: Thread-2
Thu Mar 14 14:22:20 2019 吃火锅的小伙伴-羊肉:xiaowang
退出主线程:吃火锅结束,结账走人

Process finished with exit code 0

 

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Python中的多线程模块是threading,它是用来解决Python程序中多任务处理的一个模块。通过使用threading,我们可以创建多个线程并行执行,从而提高程序的执行效率。在使用threading时,需要注意线程之间的同步问题,避免出现资源竞争等问题。同时,还需要注意线程锁、线程等待等概念,保证线程的正确执行。 ### 回答2: Python 是一种解释型脚本语言,具有高层次的语法结构和易于使用的语法特性,是一种适合编写快速成型的应用程序的开发语言。在 Python 中,多线程是一种非常重要的并发编程技术,threadingPython 标准库中提供的实现多线程的模块。 threading 模块提供了多线程程序中所需的所有操作。它支持以同步或异步方式启动线程,并提供了线程之间互斥访问共享资源的机制,同时还提供了信号量、定时器、线程池等高级功能。 Python 中的多线程机制与其他编程语言中的多线程机制非常相似。一个线程就是一个执行序列,Python线程可以共享全局变量、类、函数等数据结构。可以使用 threading.Thread 类创建新的线程,通过 start() 方法启动线程,通过 join() 方法等待线程停止运行。 Python 的 GIL(全局解释器锁)限制了多线程的并发性。GIL 是 Python 解释器用来协调多个线程之间访问共享资源的锁,它会使得同一时刻只有一个线程能够执行 Python 代码。GIL 的存在导致了 Python 的多线程并不是真正的并发,但是可以通过使用多进程或者协程来绕过 GIL 的限制。 在多线程编程中,线程间的通信是非常重要的。Python 提供了多种线程间通信的方式,如共享内存、信号量、锁、队列等。使用这些机制可以保证线程间的同步和数据的正确性。 总之,Python 中的 threading 模块提供了强大的多线程编程功能。通过深入了解和掌握这一模块,可以有效地提高并发编程的效率和质量。同时,需要注意 GIL 对多线程并发的限制,可以通过多进程或协程来规避这个问题。 ### 回答3: Python作为一种高级编程语言,在实际的应用中,多线程编程是很常见的,而多线程的核心模块就是threading。因此,本文将对Python线详解threading进行阐述。 1. 什么是多线程 多线程是指一个程序中的多个线程可以同时运行,而不是只有一个线程在运行。每个线程都是独立的执行路径,它只负责自己的代码执行,不影响其他线程的执行。 在Python中,多线程编程可以让程序执行速度更快,提高系统的利用率和效率,减少用户等待时间。 2. Python线程模块——threading详解 Python提供了多种实现多线程的模块,但最常用、也是官方推荐的是threading模块。threading模块是Python中的高级别线程模块,它对底层的_thread模块进行了更高层次的封装,使得线程模块的使用更为简便和安全。 使用线程的具体步骤: 1)导入模块:import threading 2)创建线程对象:t = threading.Thread() 3)定义线程执行的任务:def fun() 4)启动线程:t.start() 下面简单介绍一下threading模块的常用方法: ① threading.Thread(target=func, args=(), kwargs={}, name=) 参数说明: target:表示线程要执行的函数; args:表示要向线程函数传递的参数,以元组形式传入; kwargs:表示以字典形式传递的关键字参数; name:表示线程的名称。 ② t.start():表示启动线程。 ③ threading.current_thread():表示获取当前线程的实例。 ④ threading.active_count():表示当前线程在运行时的数量。 ⑤ threading.enumerate():表示获取当前正在运行的线程列表。 ⑥ t.join():表示等待当前线程执行完毕。 3. Python线程编程的注意事项 虽然Python线程编程可以提高程序效率,但也需要注意一些事项。 1)避免竞争条件:多个线程同时对同一个对象进行操作,可能会出现竞争条件,导致数据的错误处理,因此,应该使用锁机制来保证线程的同步操作。 2)避免死锁:多个线程同时互相等待对方释放资源,造成死锁,进而导致整个程序无法执行,因此,应该避免出现这种情况。 3)线程安全:有些操作是线程安全的,而有些则不是,如果不确定,需要查看方法是否线程安全。 4)多线程不一定一定比单线程快:多线程适用于多核CPU和IO密集型任务,如果是CPU密集型任务,多线程甚至可能会降低性能。 总之,Python线程编程是需要我们在实践中去不断积累经验的。希望本文能对初学者有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

王大力测试进阶之路

打赏博主喝瓶水吧!!!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值