Python 基础 线程 1

1 线程的概念

由于进程是资源拥有者,创建、撤消与切换存在较大的内存开销,因此需要引入轻型进程  即线程,

进程是资源分配的最小单位,线程是CPU调度的最小单位(程序真正执行的时候调用的是线程).每一个进程中至少有一个线程。 

2 进程和线程之间的关系

模拟一下 :

3 使用threading 模块创建线程

import threading    #导入threading模块

def sing():
    for i in range(3):
        print('...唱歌...')
        time.sleep(1)

def dance():
    for i in range(3):
    print('...跳舞...')
    time.sleep(1)

def main():
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    ti.start()
    t2.start()

if __name__ == '__main__':
    main()
    print('程序结束了....')

执行顺序:

首先程序运行时,程序从上往下走,遇到main()函数然后开始执行,执行mian()函数的函数体时又创建了两个线程我们称之为子线程,程序运行时的线程我们称之为主线程

然后子线程根据target=xxx 开始执行指定的函数(等子线程结束后主线程结束,程序结束了)

(1)线程的传递参数

给函数传递参数,使用线程的关键字args = ()进行传递参数

import threading
import time
def sing(num):
    for i in range(num):
        print('唱歌',i)
        time.sleep(1)

def dance(num):
    for i in range(num):
        print('跳舞',i)
        time.sleep(1)

def main():
    t1 = threading.Thread(target=sing,args=(3,))
    t2 = threading.Thread(target=dance,args=(3,))
    t1.start()
    t2.start()

if __name__ == '__main__':
    main()
    print('程序结束了')
"""
唱歌 0
跳舞 0
程序结束了
跳舞 1
唱歌 1
唱歌 2
跳舞 2
"""

(2) join方法  

join()方法功能:当前线程执行完后其他线程才会继续执行

import threading
import time
def sing():
    for i in range(3):
        print('唱歌',i)
        time.sleep(1)

def dance():
    for i in range(3):
        print('跳舞',i)
        time.sleep(1)

def main():
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    t1.start()
    # t1.join()    #效果是t1 结束后  t2 和主线程同时执行
    t2.start()
    t1.join()    #效果是t1 t2 子线程执行  当t1  t2 执行之后主线程才结束

if __name__ == '__main__':
    main()
    print('程序结束了')

(3).setDaemon() 方法

setDaemon方法 : 将当前线程设置成守护线程来守护主线程:

--当主线程结束后,守护线程也就结束,不管是否执行完成

--应用场景:qq多个聊天窗口,就是守护线程

注意:需要在子线程开启的时候设置成守护线程,否则无效

import threading
import time


def sing():
    for i in range(3):
        print('唱歌',i)
        time.sleep(1)

def dance():
    for i in range(3):
        print('跳舞',i)
        time.sleep(1)

def main():
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    t1.setDaemon(True)
    # t2.setDaemon(True)
    t1.start()
    t2.start()

if __name__ == '__main__':
    main()
    print('程序结束了')

(4)实例方法

线程对象的一些实例方法,了解即可

- getName(): 获取线程的名称。

- setName(): 设置线程的名称。

- isAlive(): 判断当前线程存活状态。


import time


def sing():
    for i in range(3):
        print('唱歌',i)
        time.sleep(1)

def dance():
    for i in range(3):
        print('跳舞',i)
        time.sleep(1)

def main():
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    print(t1.is_alive())
    t1.start()
    t2.start()
    print(t1.isAlive())
    # t1.setName('zs')  #给线程设置名称
    # t2.setName('ls')
    # print(t1.getName())  #获取线程名称
    # print(t2.getName())

if __name__ == '__main__':
    main()
    print('程序结束了')
"""
False
唱歌 0
跳舞 0
True
程序结束了
唱歌 1
跳舞 1
唱歌 2
跳舞 2
"""

(5) threadding 模块提供的方法

threading.currentThread(): 返回当前的线程变量。

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

threading.activeCount():

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

import time,threading


def sing():
    for i in range(3):
        print('唱歌',i)
        time.sleep(1)
    print(threading.current_thread())

def dance():
    for i in range(3):
        print('跳舞',i)
        time.sleep(1)
    print(threading.current_thread())

def main():
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    t1.start()
    t2.start()
    print(threading.current_thread())


if __name__ == '__main__':
    main()
    print('程序结束了')
import time,threading


def sing():
    for i in range(3):
        print('唱歌',i)
        time.sleep(1)


def dance():
    for i in range(3):
        print('跳舞',i)
        time.sleep(1)


def main():
    t1 = threading.Thread(target=sing)
    t2 = threading.Thread(target=dance)
    t1.start()
    t2.start()
    print(threading.active_count())


if __name__ == '__main__':
    main()
    print('程序结束了')

4 使用继承方式开启线程

(1)定义一个类继承threading.Thread 类

(2) 复写父类的方法

import threading,time

class MyThread(threading.Thread):

    def __init__(self,num):
        super().__init__()
        self.num = num

    #1
    def run(self):
        for i in range(self.num):
            print('i-->>',i)
            time.sleep(1)


if __name__ == '__main__':
    my_thread = MyThread(3)
    my_thread.start()

5  线程之间共享全局变量

import threading,time
g_num = 10

def test1():
    global g_num
    g_num += 1
    print('test1--->>',g_num)


def test2():
    print('test2--->>',g_num)

def main():
    t1 = threading.Thread(target=test1)
    t2 = threading.Thread(target=test2)
    t1.start()
    time.sleep(1)
    t2.start()

if __name__ == '__main__':
    main()

"""
test1--->> 11
test2--->> 11
"""

6  共享全局变量变量的问题

多线程开发的时候共享全局变量会带来资源竞争的效果。也就是数据不安全

效果如上:

注意:g_num += 1 在真正执行的时候会解析成很多句代码

          1   先获取g_num的值

          2   获取的值 + 1

          3   把结果保存到g_num中

模拟CPU执行,首先test1 获取cpu ,执行了g_num += 1 的前两步,

然后test2 获取了CPU,执行了g_num += 1 的三步,现在g_num的值是1

然后test1有获取了cpu,执行他的第三步,g_num = 1 将之前的数据覆盖掉了

因此才会出现上面的效果

猜你喜欢

转载自blog.csdn.net/weixin_44303465/article/details/86583872