在了解多线程前先给大家介绍下并发和并行:

  并发:多个任务一起执行 在多任务之间快速切换处理 任务数量大于cpu核数

   并行:一个cpu核处理一个任务,多个cpu核同时处理多个任务 任务数量等于或者小于cpu核数

再介绍下同步和异步 :

  同步:指线程在访问某一资源时,获得了资源的返回结果之后才会执行其他操作(先做某件事,再做某件事)

  异步: 与同步相对,是指线程在访问某一资源时,无论是否取得返回结果,都进行下一步操作;当有了资源返回结果时 系统自会通知线程

在Python中,使用threading库来创建多线程

import threading

def func1():
for i in range(6):
time.sleep(1) def func2():
for i in range(5):
time.sleep(1) # 创建线程对象
t2 = threading.Thread(target=func2) # target = 方法名
t1 = threading.Thread(target=func1, name='线程1') # 可以设置线程名字
# start 启动线程活动
# join([time]) 设置主线程会等待time秒后再往下执行,time默认为子线程结束,多个子线程之间设置的值会增加
# isAlive 返回线程是否活动的
# getName() 返回线程名
# setName() 设置线程名 a = time.time()
t2.start() # 开始执行线程2
t1.start() # 开始执行线程1
# 让主线程等待子线程执行完后再继续往下执行 同步的概念
t2.join()
t1.join()
b = time.time()
c = b - a
print(c) threading.currentThread() # 返回当前执行的线程
threading.enumerate() # 返回正在运行的所有线程(list) 正在运行指:启动后、结束前,不包括了启动前和终止后的线程
threading.activeCount() # 返回正在运行的线程数量

在threading库中调用start方法后,start方法调用了他内部的run()方法,我们可以通过继承threading重写run()方法来批量创建线程,代码如下

import threading
import requests
import time # 通过继承 threading 类来创建线程 重写run方法 因为start方法调用的就是run 重写run
class MyClass(threading.Thread):
def __init__(self, url):
self.url = url
super().__init__() # 如果要传入参数重写init方法时,一定要调用父类的init方法 # 发送requests请求 def run(self):
res = requests.get(self.url)
print('线程{},返回{}'.format(threading.current_thread(), res.status_code)) t1 = time.time()
for i in range(5):
t = MyClass('https://www.baidu.com')
t.start()
t.join()
t2 = time.time()
print(t2 - t1)

可以通过直接实例化类来创建线程对象,如果要传入参数,在重写init方法时要注意在最后调用父类的init方法,具体原因可以去查看thrreading库是如何实现的,在init方法中有很多其他的代码需要执行。

多线程共享全局变量:

在python中是使用单核来处理线程的,也就是并发并非并行,代码示例如下:

import threading

a = 100

def func1():
for i in range(100000):
global a
a += 1
print(a) def func2():
for i in range(100000):
global a
a += 1
print(a) t1 = threading.Thread(target=func1)
t2 = threading.Thread(target=func2)
t1.start()
t2.start()

当执行func1()方法时,获取全局变量为100,此时暂停切换到func2()方法,获取全局变量a为100,并进入for循环,当a循环到20000时(举例),又切换到func1()方法中开始执行for循环,此时在func1()中a的值为100,循环1次后把a的值又更新为101,造成数据不准确。

解决这个问题会用到互斥锁、同步、队列,在下一篇会给大家讲到

最新文章

  1. 苹果下如果安装nginx,给nginx安装markdown第三方插件
  2. $('div a') 与$('div>a'),.div+.div2与.div~.div2
  3. 如果选择构建ui界面方式,手写代码,xib和StoryBoard间的博弈
  4. ASP.NET CORE Web浏览器和Web服务器
  5. javascript正则表达式 —— RegExp 对象
  6. Maven安装与更新
  7. oracle系列索引
  8. mysql远程连接
  9. KMP和扩展KMP【转】
  10. 高级进阶DB2(第2版)——内部结构、高级管理与问题诊断
  11. BZOJ 2843: 极地旅行社( LCT )
  12. GNU libmicrohttpd 0.9.29 发布 - 开源中国社区
  13. poj 2762 Going from u to v or from v to u? (推断它是否是一个薄弱环节图)
  14. Java中synchronized和Lock的区别
  15. 【架构篇】OCP和依赖注入
  16. 2018-2019-2 20165316 《网络对抗技术》 Exp6 信息搜集与漏洞扫描
  17. 【pygame游戏编程】第五篇-----动画显示
  18. BootstrapTable使用实例
  19. 树莓派UFW防火墙简单设置
  20. windows 内存管理的几种方式及其优缺点

热门文章

  1. [红日安全]Web安全Day9 - 文件下载漏洞实战攻防
  2. iOS中使用block进行网络请求回调
  3. 智慧港口——基于二三维一体化GIS的港口可视化监管平台
  4. MyBatis-Plus不写任何resultMap和SQL执行一对一、一对多、多对多关联查询
  5. 借助Redis完成延时任务
  6. 【原创】(求锤得锤的故事)Redis锁从面试连环炮聊到神仙打架。
  7. JVM04——七个GC垃圾收集器,一个都不能少
  8. 双列集合Map相关面试题
  9. BrowserSync(前端利器—保存代码后,自动刷新浏览器)
  10. JavaScript中的内存释放