1、概念

线程、进程
进程是资源的集合,也就是一个程序
线程是一个程序运行的最小单位
线程是在进程里面的
默认,一个进程就只有一个线程

一个电脑有几核CPU就只能同时运行几个任务,比如4核CPU只能同时运行4个线程

我们在操作电脑时,感觉是同时运行多个任务,是因为CPU的运算速度很快,有上下文切换,我们感觉不到

python里的多线程利用不了多核CPU,比如我的电脑是8核的CPU,起100个线程,这100个线程都是在一个CPU里面执行,其他7个CPU是空闲的

因为线程之间数据是共享的,同时来处理数据会乱,GLI全局解释器锁,保证线程都在同一个CPU上运行

多进程可以利用多核CPU

  CPU密集型任务,用多进程-->消耗CPU比较多

  IO(磁盘IO,网络IO)密集型任务,用多线程-->消耗IO比较多

#1、多线程,线程之间数据是共享的

#2、多进程,进程之间数据是独立的

#3、协程,一个线程,速度很快,从头到尾都只有一个线程,利用的原理是异步IO

  Nginx   -->一个线程

2、多线程

2.1、多线程代码

串行的方式是执行完一个,再接着执行第二个

多线程是同时启用多个线程去操作

 1 def insert_db():
2 time.sleep(3)
3 print('insert_db over')
4
5 start_time = time.time()
6 for i in range(3): #串行的方式
7 insert_db()
8 end_time = time.time()
9 print('串行的执行的时间',end_time - start_time )
10
11 start_time2 = time.time()
12 #2、判断当前存活的线程个数为1个时
13 for i in range(3):
14 t = threading.Thread(target=insert_db)
15 t.start()
16
17 while threading.activeCount()!=1:
18 pass
19
20 end_time2 = time.time()
21 print('多线程执行的时间',end_time2 - start_time2)#只是主线程执行的时间,不计算子线程执行的时间

执行结果如图所示:

2.2、多线程的时间统计

 1 def insert_db():
2 time.sleep(3)
3 print('insert_db over')
4 start_time2 = time.time()
5 #2、判断当前存活的线程个数为1个时
6 for i in range(3):
7 t = threading.Thread(target=insert_db)
8 t.start()
9
10 end_time2 = time.time()
11 print('多线程执行的时间',end_time2 - start_time2)#只是主线程执行的时间,不计算子线程执行的时间

执行结果如图所示:

正常执行应该是3秒多一点,这里是因为只是主线程执行的时间,没有计算子线程执行的时间,如何解决该问题?

1.用两次循环来解决,这样代码看起来比较繁琐

 1 threads = []
2 start_time2 = time.time()
3 #2、判断当前存活的线程个数为1个时
4 for i in range(3):
5 t = threading.Thread(target=insert_db)
6 t.start()
7 threads.append(t)
8
9 for i in threads:
10 i.join()
11 end_time2 = time.time()
12 print('多线程执行的时间',end_time2 - start_time2)

2.用while循环来解决,判断当前活动的线程数为1,统计时间,如果不为1,则进入循环,不统计时间

 1 start_time2 = time.time()
2 #2、判断当前存活的线程个数为1个时
3 for i in range(3):
4 t = threading.Thread(target=insert_db)
5 t.start()
6
7 while threading.activeCount()!=1:
8 pass
9
10 end_time2 = time.time()
11 print('多线程执行的时间',end_time2 - start_time2)

2.3、多线程传参

用元组的方式传参,args=(i,)#这里传入的是一个元组,一个参数时要加,

也可以用数组的方式来传参,args=['lxy']

 1 import threading
2 import requests
3 import hashlib
4 import time
5 def down_load(url):
6 name = hashlib.md5(url.encode()).hexdigest()
7 r = requests.get(url)
8 with open('%s.jpg'%name,'wb') as fw:
9 fw.write(r.content)
10
11 l = [
12 'http://www.nnzhp.cn/wp-content/themes/QQ/images/logo.jpg',
13 'http://www.nnzhp.cn/wp-content/uploads/2016/12/2016aj5kn45fjk5-150x150.jpg',
14 'http://www.nnzhp.cn/wp-content/themes/QQ/images/thumbnail.png'
15 ]
16
17 for i in l:
18 t = threading.Thread(target=down_load,args=(i,))#args=(i,),一个参数的时候要加,
19 t.start()
20
21 while threading.activeCount() != 1:
22 pass
23
24 print('down_load over...')

2.4、多线程获取函数返回值

多线程运行函数时,是没有办法获取到函数的返回值,所以可以定义一个全局的list,把函数的返回结果存到list就可以了

1 case_result = []
2 def run_case(case_name):
3 print('run case over...')
4 case_result.append({case_name,'success'})

2.5、守护线程

守护线程,一旦主线程死掉,不管守护线程有没有执行完成,守护线程全部都结束

 1 #守护线程,一旦主线程死掉,不管守护线程有没有执行完成,全部都结束
2
3 import threading
4 import time
5
6 def talk(name):
7 print('正在和%s聊天'%name)
8 time.sleep(200)
9
10
11 def shipin(name):
12 print('正在和%s视频' % name)
13 time.sleep(200)
14
15
16 print('qq聊天窗口')
17 t1 = threading.Thread(target=talk,args=['xxl'])
18 t1.setDaemon(True)#设置线程为守护线程
19 t1.start()
20
21
22 t2 = threading.Thread(target=shipin,args=['lxy'])
23 t2.setDaemon(True)#设置线程为守护线程
24 t2.start()
25
26
27 time.sleep(5)
28 print('结束')

2.6、线程锁

多个线程同时操作同一个数据时,会有问题,这个时候需要用到线程锁

线程锁需要设置锁定时长,数据操作完成后,需要解锁,不然其他线程会进入无线等待

 1 #线程锁
2 #多个线程同时操作同一个数据的时候,会有问题
3 import threading
4 lock = threading.Lock()
5 count = 0
6 def test():
7 global count
8 lock.acquire(timeout=3000)#加锁,设置超时时间为3毫秒
9 count += 1
10 print(count)
11 lock.release()#解锁
12
13 for i in range(100):
14 t = threading.Thread(target=test)
15 t.start()

3、多进程

 1 import multiprocessing
2 import time
3 import threading
4 lock = multiprocessing.Lock()#锁
5 a = 1
6
7 def xxx():
8 pass
9
10 def test():
11 for i in range(20):#进程里可以执行多个线程
12 t = threading.Thread(target=xxx)
13 t.start()
14 time.sleep(6)
15 global a
16 with lock:#加锁,with用完之后会自动释放,因为with会自动管理上下文,进程里加锁没有啥意义
17 a += 1
18 print(a)#a的值为2
19 print('over...')
20
21 '''
22 主进程叫醒进程,进程再开始干活
23 进程是包含线程的
24 '''
25 if __name__ == '__main__':#multiprocessing要用main方法
26 for i in range(5):#6个进程--6个线程
27 p = multiprocessing.Process(target=test,name='ssz')#target:方法名,name:进程名,args:参数
28 p.start()#进程启动后,加上主进程有两个进程在运行
29 #print(p.pid)#进程ID
30
31 while len(multiprocessing.active_children())!=0:#等待
32 #print(multiprocessing.active_children())
33 pass
34 print('最后的over...')
35 print(a)#a的值为1,是因为进程之间的数据是独立的
36 #print('abc...')

python使用笔记26--多线程、多进程的更多相关文章

  1. python学习笔记(十三): 多线程多进程

    一.线程&进程 对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程, ...

  2. Python 爬虫笔记、多线程、xml解析、基础笔记(不定时更新)

    1  Python学习网址:http://www.runoob.com/python/python-multithreading.html

  3. python学习笔记——fork()创建多进程

    1 进程概述 引自 Python 多进程 fork()详解 1.1 进程 进程是程序的一次动态执行过程,它对应了从代码加载.执行到执行完毕的一个完整过程. 进程是系统进行资源分配和调度的一个独立单位. ...

  4. Python入门笔记(26):Python执行环境

    一.python特定的执行环境 在当前脚本继续进行 创建和管理子进程 执行外部命令或程序 执行需要输入的命令 通过网络来调用命令 执行命令来创建需要处理的输出 动态生成Python语句 导入Pytho ...

  5. python学习笔记26(python中__name__的使用)

    在python中,每个py文件都是一个模块,也都是一个可执行文件,即包含main方法.因此,对每个py文件,可以单独运行,也可以import它给其他客户使用,这两种情况不一样. 1. 如果模块是被导入 ...

  6. python爬虫入门八:多进程/多线程

    什么是多线程/多进程 引用虫师的解释: 计算机程序只不过是磁盘中可执行的,二进制(或其它类型)的数据.它们只有在被读取到内存中,被操作系统调用的时候才开始它们的生命期. 进程(有时被称为重量级进程)是 ...

  7. 【转】Python中的GIL、多进程和多线程

    转自:http://lesliezhu.github.io/public/2015-04-20-python-multi-process-thread.html 目录 1. GIL(Global In ...

  8. Python学习笔记16:标准库多线程(threading包裹)

    Python主要是通过标准库threading包来实现多线程. 今天,互联网时代,所有的server您将收到大量请求. server要利用多线程的方式的优势来处理这些请求,为了改善网络port读写效率 ...

  9. 在python中单线程,多线程,多进程对CPU的利用率实测以及GIL原理分析

    首先关于在python中单线程,多线程,多进程对cpu的利用率实测如下: 单线程,多线程,多进程测试代码使用死循环. 1)单线程: 2)多线程: 3)多进程: 查看cpu使用效率: 开始观察分别执行时 ...

  10. Python Web学习笔记之多线程编程

    本次给大家介绍Python的多线程编程,标题如下: Python多线程简介 Python多线程之threading模块 Python多线程之Lock线程锁 Python多线程之Python的GIL锁 ...

随机推荐

  1. Mybatis3详解(十四)----Mybatis的分页

    1.前言 在前面学习mybatis的时候,会经常对数据进行增删改查操作,使用最多的是对数据库进行查询操作,但是前面都是简单的案例,所以查询的数据量不是很大,自然查询时没有任何压力,但是如果在实际的项目 ...

  2. js--手动实现一个常见的短信验证码输入框

    前言 本文记录一下自己手动实现的一个前端常见的短信验证码输入组件,从需求到实现逐步优化的过程. 正文 1.需求分析 首先看一下效果图. 首先页面加载的时候,输入框获取焦点,当用户输入一个数字后,焦点自 ...

  3. [leetcode] 212. 单词搜索 II(Java)

    212. 单词搜索 II 这leetcode的评判机绝对有问题!!同样的代码提交,有时却超时!害得我至少浪费两个小时来寻找更优的答案= =,其实第一次写完的代码就可以过了,靠!!!第207位做出来的 ...

  4. Vue之前后端交互

    Vue之前后端交互 一.前后端交互模式 接口调用方式 原生ajax 基于jQuery的ajax fetch axios 异步 JavaScript的执行环境是「单线程」 所谓单线程,是指JS引擎中负责 ...

  5. TVM 高效保护隐私 ML

    TVM 高效保护隐私 ML 这篇文章描述了Myelin,一个在值得信赖的硬件飞地中保护隐私的机器学习框架,以及TVM如何使Myelin快速.关键的想法是,TVM,不像其它流行的ML框架,将模型编译成轻 ...

  6. eclipse左边的工程列表窗口不见了解决方案

    解决eclipse左边的工程列表窗口看不到工程目录的方法: Window->Show View->Project Explorer(如果没有Project Explorer选项,则Wind ...

  7. Python_Selenium之浏览器封装_去掉浏览器受到自动化控制横条显示及去掉是否记住密码弹窗

    封装如下: from selenium import webdriverfrom common.config_utils import configfrom selenium.webdriver.ch ...

  8. 单点突破:MySQL之索引

    前言 开发环境:MySQL5.7.31 什么是索引 在MySQL中,索引(Index)是帮助高效获取数据的数据结构. 我们可以将数据库理解为一本书,数据库中的各个数据列(column)就是目录中的章节 ...

  9. seldom 1.0 发布

    seldom 是我几个月前重启的Web UI 自动化开源项目,源项目名 pyse, 基于 unittest 和 selenium 的自动化测试框架. seldom 1.0 做为第一个正式版做了以下改进 ...

  10. TopN算法,流式数据获取前N条数据

    背景:由于业务需求,用户想要统计每周,每月,几个月,一年之中的前N条数据. 根据已有的思路无非就是对全部的数据进行排序,然后取出前N条数据,可是这样的话按照目前最优的排序算法复杂度也在O(nlog(n ...