昨天在做题的时候遇上了需要多线程来跑的程序,所以今天打算好好地去学习一下多进程
具体的理论解释在百度上比比皆是,所以这边我也不再复制粘贴
这里先直接上个程序来解释单线程与多线程
import timedef test(): print('wawawawaaw') time.sleep(2)if __name__ == '__main__': for i in range(5): test()
运行这段代码可以看到结果是一行一行进行执行的,接着看一下多线程的:
#coding:utf-8 import threadingimport timedef test(): print('waaawawawa') time.sleep(2) if __name__=='__main__': for i in range(5): t = threading.Thread(target=test) #调用线程,Thread(target=方法名) t.start() #启动
可以看到五行结果是同时执行完成的,这就是所谓的多线程
import threadingdef main(): print(threading.active_count()) #查看有几个正在运行的线程 print(threading.enumerate()) #查看正在运行线程的list print(threading.current_thread()) #查看当前的线程变量 if __name__=='__main__': main()
这里还要提一下join()方法,首先还是看两个例子:
import threadingimport timedef test(): print('waaawawawa\n') for i in range(5): time.sleep(1) print('finish\n') if __name__=='__main__': t = threading.Thread(target=test) t.start() print('all done\n')
运行结果:all done并没有出现在finish之后,这说明main函数中的几个语句是同时执行的,要想all done出现在最后,那么就要加上join()
加上join后的代码:
import threadingimport timedef test(): print('waaawawawa\n') for i in range(5): time.sleep(1) print('finish\n') if __name__=='__main__': t = threading.Thread(target=test) t.start() t.join() print('all done\n')
运行结果:all done出现在了最后
这里的join()的方法的作用就是等待至线程中止,当以上线程执行完毕后再接着执行main函数接下去的代码
接着就要提一下Queue:线程优先级队列
#coding:utf-8import threadingfrom queue import Queuearr = [[1,2,3],[2,3,4],[3,4,5],[4,5,6]]def job(l, q): for i in range(len(l)): l[i] = l[i]**2 #对传入的数组的每个值进行平方 q.put(l) #将传入的l数组放于队列中 def mulT(): q = Queue() #定义队列q threads = [] #定义一个空的线程数组,将来存放下面四个线程 for i in range(4): t = threading.Thread(target=job, args=(arr[i], q)) #生成4个线程,参数分别对应arr中的4个数组 t.start() #开始多线程 threads.append(t) #将每个线程添加进threads数组 for thread in threads: thread.join() #给每个线程都添加join方法 result = [] for j in range(4): result.append(q.get()) #将q队列中存放的4个值添加进result print(result) if __name__=='__main__': mulT()
这里只是简单的定义了一个队列,并使用了put()、get()的命令
Queue 模块中的常用方法:
- Queue.qsize() 返回队列的大小
- Queue.empty() 如果队列为空,返回True,反之False
- Queue.full() 如果队列满了,返回True,反之False
- Queue.full 与 maxsize 大小对应
- Queue.get([block[, timeout]])获取队列,timeout等待时间
- Queue.get_nowait() 相当Queue.get(False)
- Queue.put(item) 写入队列,timeout等待时间
- Queue.put_nowait(item) 相当Queue.put(item, False)
- Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
- Queue.join() 实际上意味着等到队列为空,再执行别的操作
最后就是锁的概念了
还是先看例子:
import threadingdef job1(): global A for i in range(5): A += 1 print('job1',A) def job2(): global A for i in range(5): A += 2 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()
在没有锁的情况下进行多线程打印两个不同的计算结果,可以看到,打印的结果还是有点混乱的
接着我们给两个线程上个锁:
import threadingdef job1(): #上锁的方法很简单,首先在相关线程前调用Lock()的方法,接着使用acquire()、release()两个方法来控制上锁的区域 global A,lock lock.acquire() for i in range(5): A += 1 print('job1',A) lock.release() def job2(): global A,lock lock.acquire() for i in range(5): A += 2 print('job2',A) lock.release() if __name__=='__main__': lock = threading.Lock() A = 0 t1 = threading.Thread(target=job1) t2 = threading.Thread(target=job2) t1.start() t2.start() t1.join() t2.join()
上锁以后,这两个进程就不会相互影响