Python多线程

多线程

 

1.主线程:创建一个进程的时候,会创造一个线程,这个线程就被成为主线程

一个进程里只有一个主线程

注意:python中的多线程不是真正意义上的多线程。(高速的在多个线程中进行切换,制造出多线程的假象)

2.全局锁(GIL): 在任意的指定时间里,有且只有一个线程在运行(保证python线程安全)

3. Join:等待上面的所有线程结束之后在继续往下执行

线程安全的歧义:

4.多线程复杂度较高,不建议使用(使用的话使用消息传递,写脚本的话可以使用,不用考虑脚本的阅读性):

一个程序的复杂度,和代码长度有关

用于数据库连接池

5.io操作多线程,必须要lock,acquire,release,Rlock

互斥锁:多线程对同一个文件进行操作时,当一个线程在操作时候,其它线程不能进行操作,直到该线程结束后,才能进行操作

加锁:acquire

释放锁:release

死锁:加锁后不释放

防止死锁:Rlock(可重入),在加锁中在加锁,(几个加锁要有几个解锁)

守护线程: 必须在start() 方法调用之前设置,如果不设置为守护线程程序会被无限挂起。子线程启动后,父线程也继续执行下去,当父线程执行完最后一条语句后,没有等待子线程,直接就退出了,同时子线程也一同结束。

上下文:每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。

指令指针和堆栈指针寄存器:是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。

注意:加锁后一定要释放

优点

  • 使用线程可以把占据长时间的程序中的任务放到后台去处理。
  • 用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
  • 程序的运行速度可能加快
  • 在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。

线程可以被抢占(中断)。

在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) -- 这就是线程的退让。

线程分类

  • 内核线程:由操作系统内核创建和撤销。
  • 用户线程:不需要内核支持而在用户程序中实现的线程。

threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法

  • threading.currentThread(): 返回当前的线程变量。
  • threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:

  • run(): 用以表示线程活动的方法。
  • start():启动线程活动。
  • join([time]): 等待至线程中止。这阻塞调用线程直至线程的join() 方法被调用中止-正常退出或者抛出未处理的异常-或者是可选的超时发生。
  • isAlive(): 返回线程是否活动的。
  • getName(): 返回线程名。
  • setName(): 设置线程名。

EG1:

# threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法:
import threading, time
class My(threading.Thread):
    def __init__(self, id, name, counter):
        super().__init__()
        self.id = id
        self.name = name
        self.counter = counter

    def run(self):
        print("开始")
        display(self.id, self.name, self.counter)
        print("结束")


def display(id, name, counter):
    for i in range(counter):
        print("id:{},name:{}".format(id, name))
        time.sleep(1.0)


t1 = My(1, "t1", 5)
t2 = My(2, "t2", 5)
t1.start()
t2.start()
t1.join()
t2.join()
print("退出主线程")

实行结果:

开始

id:1,name:t1

开始

id:2,name:t2

id:1,name:t1

id:2,name:t2

id:1,name:t1

id:2,name:t2

id:2,name:t2

id:1,name:t1

id:1,name:t1

id:2,name:t2

结束

结束

退出主线程

EG2:

# 线程优先级队列( Queue)
import queue, time, threading
# 循环标志
queue_flg = 0

# 自定义线程,继续threading.Thread
class Mythreading(threading.Thread):
    # 重写初始化方法,实现对象属性的赋值
    def __init__(self, id, name, queue1):
        threading.Thread.__init__(self)
        self.name = name
        self.id = id
        self.queue1 = queue1
    # 实例化对象调用start()方法时候,会自动调用run()方法
    def run(self):
        print("开始:{}".format(self.name))
        display(self.id, self.name, self.queue1)
        print("结束:{}".format(self.name))

# 当队列不为空的时候,打印一个队列元素,使用线程锁
def display(id, name, queue1):
    while not queue_flg:
        lock.acquire()
        # print(name)
        if not queue1.empty():
            print("id:{}, name:{}, queue:{} ".format(id, name, queue1.get()))
            lock.release()
        else:
            lock.release()
        time.sleep(1)

# 创建一个线程锁对象
lock = threading.Lock()
# 创建一个做大长度为100的队列
queue1 = queue.Queue(100)
# 线程名称列表
list1 = ["thread1", "thread2", "thread3", "thread4"]
# 创建线程对象后,添加的列表
list_thread = []
id = 1
# 循环list1列表,创建对象,执行start()方法
for i in list1:
    a = Mythreading(id, i, queue1)
    a.start()
    # 添加到list_thread列表
    list_thread.append(a)
    id += 1
# 创建列表,并添加队列元素
list2 = [i for i in range(5)]
lock.acquire()
for i in list2:
    queue1.put(i)
lock.release()
# 当队列不为空的时候,不进行主线程操作
while not queue1.empty():
    pass
# 结束循环
queue_flg = 1
#使当前多线完成后,在继续执行主线程
for i in list_thread:
    i.join()
print("多线程结束")

实行结果:

开始

id:1,name:t1

id:1,name:t1

id:1,name:t1

结束

开始

id:2,name:t2

id:2,name:t2

id:2,name:t2

结束

退出主线程

开始:thread1

开始:thread2

开始:thread3

开始:thread4

id:4, name:thread4, queue:0

id:2, name:thread2, queue:1

id:3, name:thread3, queue:2

id:1, name:thread1, queue:3

id:4, name:thread4, queue:4

结束:thread2

结束:thread3

结束:thread1

结束:thread4

多线程结束

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值