Python多线程

 

Python多线程的使用及其相关概念介绍

异步与多线程的区别:https://www.cnblogs.com/dream844/archive/2012/06/12/2546083.html

1. 线程的基本使用

  1.1 直接通过threading模块注册使用

# -*- coding:utf-8 -*-
# Author:Wong Du

'''
多线程的简单使用
'''
import threading
import time

def war(n):
    for i in range(10):
        print("task ", n, i)
    time.sleep(2)

# 注册线程
t1 = threading.Thread(target=war, args=("t1",))
t2 = threading.Thread(target=war, args=("t2",))

# 运行线程
t1.start()
t2.start()

# war("t1")
# war("t2")

  1.2 通过继承threading.Thead类,重写run函数方法来调用线程

# -*- coding:utf-8 -*-
# Author:Wong Du

import threading
import time

class MyThreading(threading.Thread):
    def __init__(self, n, sleep_time):
        super(MyThreading, self).__init__()
        self.n = n
        self.sleep_time = sleep_time

    def run(self):
        print("Task ", self.n)
        time.sleep(self.sleep_time)

# 注册线程
t1 = MyThreading("t1", 2)
t2 = MyThreading("t2", 4)

# 运行线程
t1.start()
t2.start()

# 等待t1线程执行完才执行后续代码
t1.join()
print("Task t1 is done...")

  1.3 多线程并行执行

 1 # -*- coding:utf-8 -*-
 2 # Author:Wong Du
 3 
 4 import threading
 5 import time
 6 
 7 # 定义一个函数任务,作为注册线程使用
 8 def war(n):
 9     print("task", n)
10     time.sleep(2)
11 
12 # 注册的线程列表
13 t_list = []
14 # 程序开始启动线程时间
15 start_time = time.time()
16 # 运行多个线程
17 for i in range(50):
18     t = threading.Thread(target=war, args=("t-%s" % i,))
19     t.start()
20     # 把注册的线程加到列表里
21     t_list.append(t)
22 
23 # join一下,等待所有线程执行完毕
24 for t in t_list:
25     t.join()
26 
27 # 计算同时开启50个线程执行完毕花费的时间
28 print("33[32;1mSpeed time is %s33[0m" % (time.time() - start_time))
多线程并行执行时间开销计算

2. 子线程和守护线程

  子线程:Python多线程的子线程和主线程相对独立,内存共享

  守护线程:通过setDaemon(True)可将线程设置成守护线程,守护线程为非守护线程服务,当非守护线程都执行完毕时,无论守护线程是否执行完毕,都将被强制结束

# -*- coding:utf-8 -*-
# Author:Wong Du

'''
子线程:Python多线程的子线程和主线程相对独立,内存共享
守护线程:通过setDaemon(True)可将线程设置成守护线程,守护线程为非守护线程服务
          当非守护线程都执行完毕时,无论守护线程是否执行完毕,都将被强制结束
'''

import threading
import time

def war(n):
    print("task", n)
    # 由主线程申请调用出来的子线程
    print("I am not main threading...".center(50, '-'), threading.currentThread())
    time.sleep(2)
    print("%s 子线程执行完毕..." % threading.currentThread())

start_time = time.time()
for i in range(50):
    t = threading.Thread(target=war, args=("t-%s" % i,))
    # 将t线程设置为守护进程
    t.setDaemon(True)
    t.start()
    # 查看当前线程信息
    print("%s is started..." % threading.currentThread())

# 查看当前线程信息及当前程序活跃的线程
print("I am main threading...".center(50, '-'), threading.currentThread(), threading.active_count())
print("33[32;1mSpeed time is %s33[0m" % (time.time() - start_time))

3. Python线程锁和递归锁

# -*- coding:utf-8 -*-
# Author:Wong Du

import threading
import time
"""
python 2.x中,会出现运算数据不正常的现象,可以通过自己加lock解决
python 3.x中,python内部进行了优化,无需加lock也不会出现异常
"""

def war():
    # 加锁
    lock.acquire()
    global num
    num += 1
    # time.sleep(0.1)
    # 释放锁
    lock.release()
    time.sleep(0.1)

num = 0
# 定义一把锁,当用锁锁住时,CPU不会进行上下文的切换,直到当前锁内的代码执行完毕
lock = threading.Lock()

start_time = time.time()
t_list = []
for i in range(50):
    t = threading.Thread(target=war)
    t.start()
    t_list.append(t)

for j in t_list:
    j.join()

print("Num:", num)
print("33[31;1mSpeed time: %s33[0m" % (time.time() - start_time))
线程锁
# -*- coding:utf-8 -*-
# Author:Wong Du

import threading
import time
"""
python 2.x中,会出现运算数据不正常的现象,可以通过自己加lock解决
python 3.x中,python内部进行了优化,无需加lock也不会出现异常
Python中,为了避免“锁内加锁”而出现锁同名导致的程序无法正常退出问题,
引入了Rlock(递归锁)的方法来区分多个用户锁
"""

def run1():
    print("num")
    lock.acquire()
    global num
    num += 10
    lock.release()
    return num

def run2():
    print("num2")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res1 = run1()
    print("Between run1 to run2...")
    res2 = run2()
    lock.release()
    print(res1, res2)
    time.sleep(3)

num, num2 = 0, 0
# 定义递归锁,当用锁锁住时,CPU不会进行上下文的切换,直到当前锁内的代码执行完毕
lock = threading.RLock()

for i in range(5):
    t = threading.Thread(target=run3)
    t.start()

# print("Num:", num)
while threading.active_count() != 1:
    pass
    # print(num, num2)
else:
    print("Threading is done...")
    print(num, num2)
线程递归锁

4. 多线程信号量控制

  Python线程处理中,Semaphore信号量可以控制“同一时间”切换上下文执行线程的数量

# -*- coding:utf-8 -*-
# Author:Wong Du

import threading
import time
"""
python 2.x中,会出现运算数据不正常的现象,可以通过自己加lock解决
python 3.x中,python内部进行了优化,无需加lock也不会出现异常
Python中,为了避免“锁内加锁”而出现锁同名导致的程序无法正常退出问题,
引入了Rlock(递归锁)的方法来区分多个用户锁
Python线程处理中,Semaphore信号量可以控制“同一时间”切换上下文执行线程的数量
"""

def war(n):
    semaphore.acquire()
    time.sleep(1)
    print("Threading:", n)
    semaphore.release()

# 定义信号量数,信号量锁住时,相当于"同一时间",只有5个线程进行上下文切换,即“同时”执行
semaphore = threading.BoundedSemaphore(5)

for i in range(30):
    t = threading.Thread(target=war, args=(i, ))
    t.start()
信号量

5. 线程的事件管理

 1 # -*- coding:utf-8 -*-
 2 # Author:Wong Du
 3 
 4 '''
 5 threading事件管理,下面为红绿灯编程实例
 6 '''
 7 import threading
 8 import time
 9 
10 # 创建一个线程事件
11 event = threading.Event()
12 
13 def light():
14     count = 0
15     # 将事件置为set状态
16     event.set()
17     while True:
18         if count > 5 and count < 10:
19             # 清除事件的set状态
20             event.clear()
21             print("33[41;1mNow is red light...33[0m")
22         elif count > 10:
23             # 将事件置为set状态
24             event.set()
25             # 重置计数
26             count = 0
27         else:
28             print("33[46;1mNow is green light...33[0m")
29         count += 1
30         time.sleep(1)
31 
32 def car(name):
33     while True:
34         # 判断事件当前是否为set状态
35         if event.is_set():
36             print("[%s] is running..." % name)
37             time.sleep(1)
38         else:
39             print("[%s] sees red light, waiting..." % name)
40             # 将事件置为wait状态,该线程卡住,只有当事件状态变为set时,才继续执行后面的代码
41             event.wait()
42             print("[%s] sees green light, running..." % name)
43 
44 light0 = threading.Thread(target=light)
45 light0.start()
46 
47 car1 = threading.Thread(target=car, args=("car1", ))
48 car1.start()
红绿灯实例

原文地址:https://www.cnblogs.com/Caiyundo/p/9487737.html