网站外部链接如何建设,wordpress 站点,wordpress获取登录密码,wordpress joomla 菜单1 认识多线程
1.1 线程的概念
线程是CPU分配资源的基本单位。当一程序开始运行#xff0c;这个程序就变成了一个进程#xff0c;而一个进程相当于一个或者多个线程。当没有多线程编程时#xff0c;一个进程相当于一个主线程#xff1b;当有多线程编程时#xff0c;一个进…1 认识多线程
1.1 线程的概念
线程是CPU分配资源的基本单位。当一程序开始运行这个程序就变成了一个进程而一个进程相当于一个或者多个线程。当没有多线程编程时一个进程相当于一个主线程当有多线程编程时一个进程包含多个线程含主线程。使用线程可以实现程序大的开发。 多线程的程序设计的特点就是能够提高程序执行效率和处理速度。 2 线程创建与管理
2.1 创建线程
Python提供了threading模块来进行线程的创建与管理创建一个线程需要指定该线程执行的任务函数名、以及该函数需要的参数示例代码如下
import threadingdef demo_one(args):for i in range(5):print(demo1在执行, i)if __name__ __main__:# 创建线程thread_one threading.Thread(targetdemo_one, args(参数,))# 设置守护线程【可选】thread_one.setDaemon(True)# 启动线程thread_one.start()1.2 设置守护线程
线程是程序执行的最小单位Python在进程启动起来后会自动创建一个主线程之后使用多线程机制可以在此基础上进行分支产生新的子线程。子线程启动起来后主线程默认会等待所有线程执行完成之后再退出。但是我们可以将子线程设置为守护线程此时主线程任务一旦完成所有子线程将会和主线程一起结束就算子线程没有执行完也会退出。
thread_one.setDaemon(True)
# 方法二
thread_one threading.Thread(targetdemo_one, args(参数,),daemonTrue)1.3 设置线程阻塞
我们可以用join()方法使主线程陷入阻塞以等待某个线程执行完毕。因此这也是实现线程同步的一种方式。参数 timeout 可以用来设置主线程陷入阻塞的时间如果线程不是守护线程即没有设置daemon为True那么参数 timeout 是无效的主线程会一直阻塞直到子线程执行结束。
# -*- coding:utf-8 -*-
import threadingdef func_one(args):for i in range(5):print(func_one在执行, i)def func_two(args):for i in range(5):print(func_two在执行, i)if __name__ __main__:# 创建线程thread_one threading.Thread(targetfunc_one, args(参数,), daemonTrue)thread_two threading.Thread(targetfunc_two, args(参数,), daemonTrue)thread_one.start()thread_two.start()print(程序因线程一陷入阻塞)thread_one.join(timeout3)print(程序因线程二陷入阻塞)thread_two.join(timeout3)print(主线程已退出)
1.4 线程间的通信
线程之间共享同一块内存。子线程虽然可以通过指定target来执行一个函数但是这个函数的返回值是没有办法直接传回主线程的。我们使用多线程一般是用于并行执行一些其他任务因此获取子线程的执行结果十分有必要。直接使用全局变量虽然可行但是资源的并发读写会引来线程安全问题。下面给出常用的两种处理方式
1.4.1 线程锁
其一是可以考虑使用锁来处理当多个线程对同一份资源进行读写操作时我们可以通过加锁来确保数据安全。Python中给出了多种锁的实现例如同步锁 Lock递归锁 RLock条件锁 Condition事件锁 Event信号量锁 Semaphore这里演示 Lock锁的使用方式
from threading import Thread, Lock
from time import sleepbook_num 100 # 图书馆最开始有100本图书
bookLock Lock()def books_lease():global book_numwhile True:bookLock.acquire()book_num - 1print(借走1本现有图书{}本.format(book_num))bookLock.release()sleep(1)def books_return():global book_numwhile True:bookLock.acquire()book_num 1print(归还1本现有图书{}本.format(book_num))bookLock.release()sleep(1)if __name__ __main__:thread_lease Thread(targetbooks_lease)thread_return Thread(targetbooks_return)thread_lease.start()thread_return.start()1.4.2 queue队列
或者我们可以采用Python的queue模块来实现线程通信。Python中的queue模块实现了多生产者、多消费者队列特别适用于在多线程间安全的进行信息交换。该模块提供了4种我们可以利用的队列容器
队列当中的方法
Queue(maxsize5) # 创建一个FIFO队列并制定队列大小若maxsize被指定为小于等于0则队列无限大Queue.qsize() # 返回队列的大致大小注意并不是确切值所以不能被用来当做后续线程是否会被阻塞的依据Queue.empty() # 判断队列为空是否成立同样不能作为阻塞依据Queue.full() # 判断队列为满是否成立同样不能作为阻塞依据Queue.put(item, blockTrue, timeoutNone) # 投放元素进入队列block为True表示如果队列满了投放失败将阻塞该线程timeout可用来设置线程阻塞的时间长短秒
# 注意如果block为False如果队列为满则将直接引发Full异常timeout将被忽略在外界用try处理异常即可
Queue.put_nowait(item) # 相当于put(item, blockFalse)Queue.get(blockTrue, timeoutFalse) # 从队列中取出元素block为False而队列为空时会引发Empty异常
Queue.get_nowait() # 相当于get(blockFalse)Queue.task_done() # 每个线程使用get方法从队列中获取一个元素该线程通过调用task_done()表示该元素已处理完成。Queue.join() # 阻塞至队列中所有元素都被处理完成即队列中所有元素都已被接收且接收线程全已调用task_done()。生产者消费者实例
# -*- coding:utf-8 -*-
import threading
from queue import Queue
from random import choicedealList [红烧猪蹄, 卤鸡爪, 酸菜鱼, 糖醋里脊, 九转大肠, 阳春面, 烤鸭, 烧鸡, 剁椒鱼头, 酸汤肥牛, 炖羊肉]queue Queue(maxsize5)
# 厨子生产
def func_one(name):for num in range(4):# 随机从列表当中获取一个元素data_veg choice(dealList)queue.put(data_veg, blockTrue)print(f厨师{name}给大家做了一道{data_veg})# 客人消费
def func_two(name:str):for num in range(3):veg_data queue.get()print(f客人{name}吃掉了:{veg_data})queue.task_done()if __name__ __main__:# 创建生产者线程总共三个厨子,相当于给每个厨子创建了一个县城for name in [张三, 李四, 王五]:thread_one threading.Thread(targetfunc_one, args(name,))thread_one.start()# 创建消费者四个线程for name in [客人甲, 客人乙, 坤哥, 凡哥]:thread_two threading.Thread(targetfunc_two, args(name,))thread_two.start()queue.join()