线程


线程是操作系统直接支持的执行单元

线程:运行是没有先后顺序的

同时运行的理解:
实际上是多个线程之间轮流执行的,就是将一个时间段分成若干个时间片,每个线程只运行一个时间片,由于时间片极短,而且电脑运行极快,线程之间切换也极快,几乎可以看做是并行运行的,也就是说可以看成是同时运行的.但实际却不是的同时运行的.

  • 线程的实现

python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便地被使用

import time
import threading
def sing():
    for i in range(5):
        print("正在唱111")
        time.sleep(1)
def dance():
    for i in range(10):
        print("正在跳222")
        time.sleep(1)
def main():
    t1=threading.Thread(target=sing)
    t2=threading.Thread(target=dance)
    t1.start()
    t2.start()
    while True:
        print(len(threading.enumerate()))
        if len(threading.enumerate())<=1:
            break
        time.sleep(1)
if __name__=="__main__":
    main()

使用Thread类完成创建线程(必须要用run方法)

import time
import threading
class MyThread(threading.Thread):
    def run(self):
        for i in range(3):
            time.sleep(1)
            print("hello")
        self.p()
    def p(self):
        print("hi")
def main():
    t= MyThread()
    t.start()#创建一个实例对象只能创建一个线程可以在run里面调用这个类的其他方法
if __name__=="__main__":
    main()

在方法中传入参数
threading.Thread(target=text,args=(XXX,)
第二个参数args是一个元组,如果只传递一个值,就只需要i, 如果需要传递多个参数,那么还可以继续传递下去其他的参数。特别注意其中的逗号不能少,少了就不是元组了,就会报错

import time
import threading
g_num=0
def text(num):
    global g_num
    for i in range(num):
        g_num+=1
        print("text1=%d"%g_num)
def text2(num):
    global g_num
    for i in range(num):
        g_num+=1
        print("text2=%d"%g_num)
def main():
    t1=threading.Thread(target=text,args=(100,))
    t2 =threading.Thread(target=text2,args=(100,))
    t1.start()
    t2.start()
    time.sleep(1)
    print("g_num=%d"%g_num)
if __name__=="__main__":
    main()
  • 同步与互斥

同步:按照预定的先后次序进行执行 先A后B
互斥锁:保证每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性
创建互斥锁 每一个线程在开始和结束都要进行锁定和释放两个操作

#创建锁
mutex=threading.Lock()#默认是没有上锁
#锁定
mutex.acquire()
#释放
mutex.release()

给资源加锁, 而是用锁去锁定资源,你可以定义多个锁, 像下面的代码, 当你需要独占某一资源时,任何一个锁都可以锁这个资源

with 后面有两个必须执行的操作:__enter__ 和 _exit__
不管里面的操作结果如何,都会执行打开、关闭
打开锁、处理内容、释放锁
with self.lock:
	do
  • Join

知识点一:
当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束,例子见下面一。
知识点二:
当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止,例子见下面二。
知识点三:
此时join的作用就凸显出来了,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程在终止,例子见下面三。
知识点四:
join有一个timeout参数:
当设置守护线程时,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。
没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。

线程也要都在主线程之前执行完毕
for thread in treadcawl:#threadcrawl里面是线程集合
    thread.join()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值