Python3进阶篇——多线程的应用

下面我们来想象一个场景,放学后教室要打扫卫生,我们一般是怎么分配任务的,一般来讲不可能说小明你去把今天的卫生全部打扫了,这样就太残暴了;一般来说,我们分组来打扫,比如小明打扫第一组,小刚打扫第二组,小智打扫第三组……这样合作,很快就可以将打扫卫生这个任务完成了;那么对于我们程序来讲也是一样的,我需要下载音乐,如果就是在一个main函数里面进行,这就好比让一个人打扫全部的卫生,虽然也能够完成任务,但是速度肯定是很慢的,这样我就可以创建新的进程,按照歌手的名字同时进行下载,这样效率就会快很多了,那么这就是多线程的作用和优势;

那么我们再来讲一下什么是线程,线程和进程有什么样的区别呢?

在创建线程任务之前呢,先来看一下程序运行后有几个线程,这些线程的信息我们可以怎么样获取:

import threading        # 先导入关于线程操作的库

def main():
    print(threading.active_count())     # 查看当前有几个线程在运行
    print(threading.enumerate())        # 查看当前有哪些线程在运行
    print(threading.current_thread())   # 查看当前运行的哪个线程

if __name__ == '__main__':
    main()
    
# 输出结果:
# 1
# [<_MainThread(MainThread, started 14340)>]
# <_MainThread(MainThread, started 14340)>

我们会发现,当程序运行后,因为只有main函数在运行,所以就只有一个线程,就是我们的MainThread,下面我们来看下怎么添加新的线程任务:

import threading

def new_thread():        # 这个就是我们创建的线程需要完成的任务
    print('这是我的线程信息:%s' % threading.current_thread())

def main():
    add_thread = threading.Thread(target=new_thread)    # 创建一个新的线程,线程的任务是new_thread
    add_thread.start()    # 开始执行线程任务

if __name__ == '__main__':
    main()

# 输出结果:
# 这是我的线程信息:<Thread(Thread-1, started 15624)>

通过下面的例子,我们发现当有程序有两个线程的时候,他们是同时工作的:

import threading
import time

def n1_thread_job():
    for i in range(10):
        print(i)
        time.sleep(0.1)    # 加入延迟时为了造成时间差,使结果更加明显

def n2_thread_job():
    for i in range(5):
        print('hahaha')
        time.sleep(0.1)

def main():
    n1_thread = threading.Thread(target=n1_thread_job)
    n2_thread = threading.Thread(target=n2_thread_job)
    n1_thread.start()
    n2_thread.start()

if __name__ == '__main__':
    main()

# 输出结果:
# 0
# hahaha
# 1
# hahaha
# hahaha
# 2
# 3
# hahaha
# 4
# hahaha
# 5
# 6
# 7
# 8
# 9

下面我们设想一个情况,我想当一个线程完成之后,在开始另一个线程,那应该怎么办呢?

import threading
import time

def n1_thread_job():
    for i in range(10):
        print(i)
        time.sleep(0.1)

def n2_thread_job():
    for i in range(2):
        print('hahaha')
        time.sleep(0.1)

def main():
    n1_thread = threading.Thread(target=n1_thread_job)
    n2_thread = threading.Thread(target=n2_thread_job)
    n1_thread.start()
    n1_thread.join()        # 我们可以用join()方法,让n1_thread线程执行完毕之后再执行后面的语句
    n2_thread.start()
    print('done!')

if __name__ == '__main__':
    main()

# 输出结果:
# 0
# 1
# 2
# 3
# 4
# hahaha
# done!
# hahaha

下面问题来了,我们有时候执行方法是有返回值的,如果添加到进程中,return肯定是不行的,那么返回值有要怎么获取呢?

import threading
from queue import Queue    # 我们就是将返回值放在这里的

def calc(list1,q):        # 进程需要完成的工作,计算传进来每个参数的平方
    for i in range(len(list1)):
        list1[i] = list1[i] ** 2
    q.put(list1)    # 将计算的结果放在q这个空间中

def create_thread(data):
    q = Queue()     # 相当于创建了一个空间来存储返回的结果
    threads = []    # 用来存放进程的列表
    for i in range(len(data)):    # 我们看一共有几组数据,然后就创建几个进程
        t = threading.Thread(target=calc,args=(data[i],q))    # 创建新的进程,并且把数据传参进去
        t.start()    # 开始进程
        threads.append(t)       # 将创建的进程添加到列表中
    for thread in threads:
        thread.join()      # 通过遍历我们要将所有的结果都计算完毕之后,再提取出来,显示结果
    result = []            # 用来保存结果
    for i in range(len(data)):
        result.append(q.get())    # 将结果一个一个提取出来,然后添加到列表中
    print(result)    # 输出结果

if __name__ == '__main__':
    data = [[3,4,3,2],[2,4],[5,4,3,2,9],[3]]    # 需要处理的数据
    create_thread(data)

# 输出结果:
# [[9, 16, 9, 4], [4, 16], [25, 16, 9, 4, 81], [9]]

我们可以用queue创建一个空间,然后将结果都先暂存在这块中间里面,最后一次性将计算好的结果从这块空间里面提取处理;

最后一块内容,上面的多个线程之间是没有什么关联的,但是接下来我需要处理的数据有一个公用的变量,那么同一时间势必只能有一个变量能被使用或修改,那么我们可以在一个进程在使用这个变量的时候,将这个变量先锁住,当使用完毕之后再解锁,这样就不会产生冲突了:

import threading

def job1():
    global data,lock
    lock.acquire()
    for i in range(5):
        data += 1
        print(data)
    lock.release()

def job2():
    global data,lock
    lock.acquire()
    for i in range(5):
        data *= 2
        print(data)
    lock.release()

if __name__ == '__main__':
    data = 0
    lock = threading.Lock()
    thread1 = threading.Thread(target=job1)
    thread2 = threading.Thread(target=job2)
    thread1.start()
    thread2.start()
    
# 输出结果:
# 1
# 2
# 3
# 4
# 5
# 10
# 20
# 40
# 80
# 160

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值