0
点赞
收藏
分享

微信扫一扫

python进阶学习03_多线程(一)

快乐码农Alan007 2022-01-08 阅读 116

多线程(一)

  1. 创建多线程
  2. 多线程特性
  3. 线程锁

学习视频链接:python多线程

1.创建多线程

p66
多线程类似于同时执行多个不同程序
线程也叫轻量级进程,是操作系统能够进行运算调度的最小单位,它被包涵在进程之中,是进程中的实际运作单位。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行

  • 普通方式创建
  • 以类的方式创建
#普通方式创建
'''
import threading
import time
def test(x):
    print('普通方式创建多线程',x)
    time.sleep(2)

if __name__=='__main__':
    t1 = threading.Thread(target=test, args=(1,))  # target是要执行的函数名(不是函数),args是函数对应的参数,以元组的形式存在
    t2 = threading.Thread(target=test, args=(2,))
    t1.start()
    t2.start()
'''

#以类的方式创建
import threading
import time
'''
super(Net, self).__init__()
Python中的super(Net, self).__init__()是指首先找到Net的父类(比如是类NNet),
然后把类Net的对象self转换为类NNet的对象,然后“被转换”的类NNet对象调用自己的init函数,
其实简单理解就是子类把父类的__init__()放到自己的__init__()当中,这样子类就有了父类的__init__()的那些东西。
'''
class mythread(threading.Thread): #继承父类threading.Thread
    def __init__(self,n):
        super(mythread, self).__init__()
        self.n=n
    def run(self):  #重构run函数必须写
        print('以类的方式创建多线程',self.n)
        time.sleep(2)
if __name__=='__main__':
    t1=mythread(1)
    t2=mythread(2)
    t1.start()
    t2.start()

打印如下:

以类的方式创建多线程 1
以类的方式创建多线程 2

2.多线程特性

p67
查看当前线程:threading.current_thread()
查看活动的线程:threading.active_count()
time模块与时间戳和时间相关的重要函数
time.time() 生成当前的时间戳,格式为10位整数的浮点数。
time.strftime()根据时间元组生成时间格式化字符串。
time.strptime()根据时间格式化字符串生成时间元组。time.strptime()time.strftime()为互操作。
time.localtime()根据时间戳生成当前时区的时间元组。

  1. 知识点一:
    当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束
  2. 知识点二:
    当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止。
  3. 知识点三:
    此时join的作用就凸显出来了,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程在终止

守护线程:
主线程结束,子线程也立马结束。必须在start() 方法调用之前设置

#守护线程
import threading
import time
def run(n):
    print('task',n)
    time.sleep(1)
    print('3s')
    time.sleep(1)
    print('2s')
    time.sleep(1)
    print('1s')

if __name__ == '__main__': #主线程
    t=threading.Thread(target=run,args=('t1',))
    t.setDaemon(True) #设置子线程为守护线程,守护主线程。主线程结束,子线程也立马结束。必须在start() 方法调用之前设置
    t.start()
    print('end')

打印结果(未加守护线程)

task t1
end
3s
2s
1s

加守护线程

task t1
end

线程同步join
主线程一直等待全部的子线程结束之后,主线程自身才结束

import threading
import time

#join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程在终止
def run(n):
    print('task',n)
    time.sleep(1)
    print('5s')
    time.sleep(1)
    print('3s')
    time.sleep(1)
    print('1s')
if __name__ == '__main__':
    t=threading.Thread(target=run,args=('t1',))
    # t.setDaemon(True)    #把子线程设置为守护线程,必须在start()之前设置
    t.start()
    t.join()     #设置主线程等待子线程结束.主线程一直等待全部的子线程结束之后,主线程自身才结束
    print('end')

打印结果(未加join)

taskend 
t1
5s
3s
1s

加join

task t1
5s
3s
1s
end

3.线程锁(互斥锁和递归锁)

p68、p69
以下为代码示例:说明(100个线程同时会操作x这个数,如果第五个和第六个同时操作就会乱。加了锁后每次都是一个线程操作x)

#线程锁
'''
#互斥锁
import threading
def run():
    global x
    lock.acquire() #申请锁
    x+=1 #每起一个线程,x就会加1.最后为100
    lock.release() #释放锁

if __name__=='__main__':
    x=0
    res=[]
    lock=threading.Lock() #实例化线程锁
    for i in range(100): #100个线程
        t=threading.Thread(target=run) #t为线程
        t.start()
        res.append(t)
    for t in res:
        t.join()    #设置主线程等待子线程结束.主线程一直等待全部的子线程结束之后,主线程自身才结束
    print(x) #100
'''

#递归锁 RLcok类的用法和Lock类一模一样,但它支持嵌套,在多个锁没有释放的时候一般会使用RLock类
#如下 run3->run1时有两个锁(嵌套)  部分代码
import threading
def run1():
    lock.acquire()
    global x
    x+=1
    lock.release()
def run2():
    lock.acquire()
    global y
    y+=1
    lock.release()
def run3():
    lock.acquire()
    r1=run1()
    r2=run2()
    lock.release()
if __name__=='__main__':
    x=0
    y=0
    lock=threading.RLock

作业:

'''
在一个线程中,每秒循环输出当前的年月日时分秒;
于此同时,在另一个线程中,实现张三的姓名每2秒打印输出4次结束。
注意:都需要使用类和继承实现功能
'''
import threading
import time
class mythread1(threading.Thread): #继承父类threading.Thread
    def __init__(self,):
        super(mythread1, self).__init__()
    def run(self):  #重构run函数必须写
        while True:
            time.sleep(1) #暂停1秒
            print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())) #打印时间

class mythread2(threading.Thread): #继承父类threading.Thread
    def __init__(self,name):
        super(mythread2, self).__init__()
        self.name=name
    def run(self):  #重构run函数必须写
        i=0
        while i<4:
            time.sleep(2)
            print(self.name)
            i+=1
if __name__=='__main__':
    t1=mythread1()
    t2=mythread2('张三')
    t1.start()
    t2.start()

打印结果:(部分)

2022-01-08 00:43:32
张三
2022-01-08 00:43:33
2022-01-08 00:43:34
张三
2022-01-08 00:43:35
2022-01-08 00:43:36
张三
2022-01-08 00:43:37
2022-01-08 00:43:38
张三
2022-01-08 00:43:39
2022-01-08 00:43:40
2022-01-08 00:43:41
2022-01-08 00:43:42
举报

相关推荐

0 条评论