Python学习 之 线程

文章目录

  • 开启线程
    • 方式1: 直接定义线程代码
    • 写法2: 自定义类
  • 守护线程 - 报活示例
  • 高级用法
    • 线程锁
    • 线程队列 - queue - 处理数据加锁的问题
    • 信号量 - semaphore
    • 事件 - Event - 等待状态变更
    • 计时器 - Timer


开启线程

方式1: 直接定义线程代码

from threading import Thread


# 写法 1
def f(name): pass


if __name__ == "__main__":
    t = Thread(target=f, args=("Tim",))
    t.start()


写法2: 自定义类

from threading import Thread


# 写法 2: 偷懒没有写 init 方法
class MyThread(Thread):
    def run(self, name): pass
    

if __name__ == "__main__":
    t = MyThread()
    t.run("Tom")


守护线程 - 报活示例

""" 当主线程回收所有资源之后, 守护线程才会结束 """

from threading import Thread
import time


def task_d():
    while 1:
        print("still alive..")
        time.sleep(0.5)


def task():
    for i in range(5):
        print("task %s" % i)
        time.sleep(1)


if __name__ == "__main__":
    t = Thread(target=task)

    td = Thread(target=task_d)
    td.daemon = True

    t.start()
    td.start()

	# 1. 写上 t.join(), main end 会等待 t 结束后再打印
    # 2. 不写 t.join(), main end 不会等待 t 结束后再打印
    # 所以 t.join 写不写取决于逻辑是否需要按顺序执行
    t.join()

    print("end main")


高级用法

线程锁

from threading import Thread, Lock
import time

n = 100

def task():
    global n
    
    # 这种写法会在内部代码完成后自动释放锁
    with mutex:
        tmp = n
        time.sleep(0.1)
        n = tmp-1


if __name__ == "__main__":
    # 方便 join 所有线程
    l = []
    mutex = Lock()
    
    for i in range(100): 
    	# 由于进程内变量共享, 所以不需要将锁作为参数传给线程
        t = Thread(target=task)
        l.append(t)
        t.start()

	# 因为需要将计算后的值输出, 所以必须 join() 所有的线程, 等待计算完成
    for i in l:
        i.join()

    print("main end", n)


线程队列 - queue - 处理数据加锁的问题

import queue

# 队列: 先进先出
q = queue.Queue(3) 

q.put(1)
q.put(2)
print(q.get())


# 堆栈: 后进先出, Last in first out
q = queue.LifoQueue(3)

q.put(1)
q.put(2)
print(q.get())


# 优先级队列, 数字越小优先级越高, 尽量优先级不重复
q = queue.PriorityQueue(3) 

q.put((10, 1))
q.put((100, True))
q.put((-10, "string")) 

print(q.get())


信号量 - semaphore

  • 相当于有总数的多线程
  • 完成一个, 再执行一个
from  threading import Thread, Semaphore, current_thread
import time, random

sm = Semaphore(5)

def task():
    with sm:
        print("%s is laing" % current_thread().getName())
        time.sleep(random.randint(1, 3))


if __name__ == "__main__":
    for i in range(20):
        t = Thread(target=task)
        t.start()


事件 - Event - 等待状态变更

from threading import Thread, Event
import time

def check():
    print("check mysql")
    time.sleep(5)
    # 设置状态为 True
    e.set()
    print("check complate")

def conn():
    count = 1
    while not e.is_set():
        if count > 3:
            raise TimeoutError("超时")
        print("try to connect Mysql time %s" % count)
        # 等待信号量变为 True, 参数为等待时间
        e.wait(2)
        count += 1
    
    # 如果 e 被 set() 设置为 True, 则会执行下边的代码
    print("connect complate")


if __name__ == "__main__":
    e = Event()
    # 拿到信号量的状态
    print(e.isSet())

    t1 = Thread(target=check)
    t2 = Thread(target=conn, name="t2")
    t3 = Thread(target=conn, name="t3")

    t1.start()
    t2.start()
    t3.start()

    # 重置信号为 False
    e.clear()


计时器 - Timer

from threading import Timer

def hello(name):
    print("hello world %s" % name)


t = Timer(1, hello, args=("Tim",))
t.start()

你可能感兴趣的:(Python)