多线程threading学习

1 线程

import threading

def main():
    
    print(threading.active_count()) #看一下目前有多少个激活了的线程
    print(threading.enumerate()) #看一下这些线程是哪几个
    print(threading.current_thread()) #看一下现在在用的是哪个线程
    
if __name__ == '__main__':
    main()

在这里插入图片描述
可以看到现在有四个线程,执行的是主线程

2 添加线程

import threading

def thread_job():
    print("This is an add Thread,number is %s" % threading.current_thread())
    

def main():
    added_thread = threading.Thread(target = thread_job) 
    # 添加一个线程,参数里传进一个可执行的方法
    added_thread.start() #线程开始
#    print(threading.active_count()) #看一下目前有多少个激活了的线程
#    print(threading.enumerate()) #看一下这些线程是哪几个
#    print(threading.current_thread()) #看一下现在在用的是哪个线程
    
if __name__ == '__main__':
    main()
    

This is an add Thread,number is <Thread(Thread-6, started 5508)>
添加了一个Thread-6线程

import threading
import time

def thread_job():
    print("T1 start\n" )
    for i in range(10):
        time.sleep(0.1)#每次暂停0.1,一共十次暂停1s
    print('T1 finish\n')
    

def main():
    added_thread = threading.Thread(target = thread_job,name = 'T1') 
    # 添加一个线程,参数里传进一个可执行的方法
    added_thread.start() #线程开始
    print('all Done\n')
    
    
if __name__ == '__main__':
    main()

在这里插入图片描述
3 join()

可以看到all Done并不是等到T1 finish这行语句执行完的,说明这个added_thread.start()print('all Done\n')两条语句是同时执行的

为了让这两个语句能够先后执行:

import threading
import time

def thread_job():
    print("T1 start\n" )
    for i in range(10):
        time.sleep(0.1)#每次暂停0.1,一共十次暂停1s
    print('T1 finish\n')
    

def main():
    added_thread = threading.Thread(target = thread_job,name = 'T1') 
    # 添加一个线程,参数里传进一个可执行的方法
    added_thread.start() #线程开始
    added_thread.join() #表示等待added_thread任务执行完之后才开始后面的代码
    print('all Done\n')
    
    
if __name__ == '__main__':
    main()

加了一个join,等待程序执行完毕,开始后面的代码

import threading
import time

def T1_job():
    print("T1 start\n" )
    for i in range(10):
        time.sleep(0.1)#每次暂停0.1,一共十次暂停1s
    print('T1 finish\n')
    
def T2_job(): #T2做的任务耗时更少
    print("T2 start\n" )
    print('T2 finish\n')
    

def main():
    added_threadT1 = threading.Thread(target = T1_job,name = 'T1') 
    # 添加一个线程,参数里传进一个可执行的方法
    added_threadT2 = threading.Thread(target = T2_job,name = 'T2') 
    # 添加一个线程,参数里传进一个可执行的方法
    added_threadT1.start() #线程开始
    added_threadT2.start() #线程开始
    print('all Done\n')
    
    
if __name__ == '__main__':
    main()

在这里插入图片描述
我们能看到,T1开始后,T2也开始,但是因为T2耗时更少,所以马上就结束了,T1等到all Done之后才结束added_threadT1.start()added_threadT2.start()print('all Done\n')开始有先后,但是处理是同时进行的,耗时久的后结束

import threading
import time

def T1_job():
    print("T1 start\n" )
    for i in range(10):
        time.sleep(0.1)#每次暂停0.1,一共十次暂停1s
    print('T1 finish\n')
    
def T2_job(): #T2做的任务耗时更少
    print("T2 start\n" )
    print('T2 finish\n')
    

def main():
    added_threadT1 = threading.Thread(target = T1_job,name = 'T1') 
    # 添加一个线程,参数里传进一个可执行的方法
    added_threadT2 = threading.Thread(target = T2_job,name = 'T2') 
    # 添加一个线程,参数里传进一个可执行的方法
    added_threadT1.start() #线程开始
    added_threadT2.start() #线程开始
    added_threadT1.join() #等待T1结束之后才进行后面的操作
    print('all Done\n')
    
    
if __name__ == '__main__':
    main()

在这里插入图片描述

4 Queue
多线程运算的结果放在队列中,对每一个线程的队列,放入主线程中,再取出

import threading
import queue

def job(name,lis,q):#传进来一个列表
    #定义一个job,对列表中的每一个值进行平方的运算
    for i in range(len(lis)):
        lis[i] = lis[i]**2
    q.put(lis) #把小列表的处理结构放到q里面
    print(str(lis) + ' has been done\n')
     
#返回得出来的结果
#return L不能使用,因为线程中的返回值是得不到的,所以需要构建一个列表去得到
def multithreading(data):
    q = queue.Queue() #存放所有线程返回的结果
    threads = [] #存放所有的线程
    
    for i in range(4):#定义4个线程
        threadName = 'Thread' + str(i)
        t = threading.Thread(target = job,args = (threadName,data[i],q))
        #target后面只放方法索引job,具体参数放在后面的args里面
        #每一个线程对应处理data里面一个小列表,如[1,2,3]
        print(threadName + ' start\n')
        t.start()        
#        print(data[i])
        threads.append(t)#threads得到的是一个线程列表,里面存放的是各个线程
        
    for thread in threads:
        thread.join() 
        # 将所有线程join到主线程里面去,等待所有线程完了之后才进行后面的操作
    
    results = []   
    for _ in range(4):#得到q里面的值
        results.append(q.get()) #从q里面拿四次值,拿出来放到result里面去        
    return results
        
if __name__ == '__main__':  
    data = [[1,2,3],[3,4,5],[4,4,4],[5,5,5]] #四个线程同时处理四个小列表
    results = multithreading(data)  
    print(results)
    

在这里插入图片描述
5 效率问题
python中多线程不一定有效率提高的效果
多线程有一个全局的控制,并不是把任务平均分给每个线程同时做
python只能让一个线程在同一个时间运算,只是不同的线程在相互切换
在这里插入图片描述

这里采用normal方法和multithreading的方法对比:
普通方法一个线程执行四遍,多线程方法,四个线程执行一遍,看看是否是多线程会提高效率

import threading
import queue
import time
import copy

def job(name,lis,q):#传进来一个列表
    res = sum(lis)
    q.put(res)
     
def multithreading(data):
    q = queue.Queue() #存放所有线程返回的结果
    threads = [] #存放所有的线程
    
    for i in range(4):#定义4个线程
        threadName = 'Thread' + str(i)
        t = threading.Thread(target = job,args = (threadName,copy.copy(data),q))
        #target后面只放方法索引job,具体参数放在后面的args里面
        
#        print(threadName + ' start\n')
        t.start()        
#        print(data[i])
        threads.append(t)#threads得到的是一个线程列表,里面存放的是各个线程
        
#    for thread in threads:
#        thread.join() 
#        # 将所有线程join到主线程里面去,等待所有线程完了之后才进行后面的操作
    
    [t.join() for t in threads]#与上面的for循环作用一样
    
    total = 0   
    for _ in range(4):#得到q里面的值
        total += q.get()        
    return total


def nomal(data):
    total = sum(data)
    return total
        
if __name__ == '__main__':  
    data = list(range(1000000))#得到一个列表
    s_t = time.time()
    nomal_total = nomal(data*4)#这个列表扩大四倍,用普通方法求和
    #一个线程求和四倍数据所用的时间
    print('nomal:',time.time()-s_t)
    print(nomal_total)
    s_t = time.time()
    multithreading_total = multithreading(data)  
    #四个线程求和一倍数据所有的总时间
    print('multithreading:',time.time()-s_t)  
    print(multithreading_total)

在这里插入图片描述
同时只有一个线程在工作,实际上减少的时间是读写所节省出来的时间
如果要使很多数据的处理同时进行,那么就需要multiprocess,多进程

6 Lock

import threading

#定义两个任务,都对A进行操作,看会怎么样
def job1():
    global A
    for i in range(10):
        A += 1
        print('job1:',A)
           
def job2():
    global A
    for i in range(10):
        A += 10
        print('job2:',A)
    
if __name__ == '__main__':
    A = 0
    #开两个线程,两个线程分别做不同的任务
    t1 = threading.Thread(target = job1)
    t2 = threading.Thread(target = job2)
    t1.start()
    t2.start()
    t1.join()
    t2.join()

我们可以看到job1,job2同时进行,而且打印的比较乱,每次运行的过程都是不确定的
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
如果想要job1进行完了之后才进行job2,那么就要把job1给lock起来

import threading

#定义两个任务,都对A进行操作,看会怎么样
def job1():
    global A,lock
    lock.acquire()
    for i in range(10):
        A += 1
        print('job1:',A)
    lock.release()
           
def job2():
    global A,lock
    lock.acquire()
    for i in range(10):
        A += 10
        print('job2:',A)
    lock.release()
    
if __name__ == '__main__':
    lock = threading.Lock() #实例化一个lock对象
    A = 0
    #开两个线程,两个线程分别做不同的任务
    t1 = threading.Thread(target = job1)
    t2 = threading.Thread(target = job2)
    
    t1.start() #t1开始之后,进入锁锁住,知道运行结束,才开始t2的任务
    t2.start()
    t1.join()
    t2.join()

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值