线程

进程和线程:

  进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。

注意:两个都是过程

线程一个特点:

  一个进程中,多个线程共享资源

线程和进程区别:

  1. 线程的创建开销小于进程, 创建速度快

  2. 同一进程下的多个线程共享该进程的地址空间(资源)

主线程影响其他线程:

  是因为线程的概念:

  一个进程内默认就会有一个控制线程,该控制线程可以执行代码从而创建新的线程,

  该控制线程的执行周期就代表该进程的执行周期

1.一个进程内不开子进程,也不开'子线程' : 主线程结束,该进程就结束

2.当一个进程内开启子进程时 : 主线程结束,主进程要等,等所有子进程运行完毕,给儿子收尸.

3.当一个进程内开启多个线程时 :

  主线程结束并不意味着进程结束,

  进程的结束指的是该进程内所有的线程都运行完毕,才应该回收进程.

简单点说,就是:

  主进程等子进程, 是主进程活都干完了

  主线程等子线程,是主进程还没有干完活

  (所有的线程都干完活了,该进程才算干完活了)

子进程和线程的id号 验证内存空间

  1. import os
  2. from multiprocessing import Process
  3.  
  4. n = 100
  5. def func():
  6. global n
  7. n = 1
  8. print('子',n,os.getpid())
  9.  
  10. if __name__ == '__main__':
  11. p = Process(target=func,)
  12. p.start()
  13. print('主',n,os.getpid())
  14. # 主 100 8852 主进程和子进程的id号不一样,说明进程间的内存空间是隔离的
  15. # 子 1 4716 子进程修改变量,主进程感觉不到,说明进程间的内存空间是隔离的

全局变量的修改,验证内存空间

  1. import os
  2. from threading import Thread
  3.  
  4. n = 100
  5.  
  6. def func():
  7. global n
  8. n = 1
  9. print(current_thread().getName(), n, os.getpid())
  10.  
  11. if __name__ == '__main__':
  12. t = Thread(target=func,name = func’) #给子线程起名字,不写,默认 Thread-1.Thread-2.....
  13. t.start()
  14. print(current_thread().getName(), n, os.getpid())
  15.  
  16. # func 1 1088 子线程和主线程的id号一样,说明主线程和子线程在一个进程空间里
  17. # MainThread 1 1088 子线程修改变量n = 1,主线程能感知到,说明线程间共享数据

进程可以看进程号

线程只能看名字了

getName() 测试的时候用的较多

enumerate()    以列表的形式列出当前所有活着的线程

active_count()    统计当前所有活着的线程的个数

  1. import time
  2. from threading import Thread, active_count, enumerate 需要导入threading模块中这两个方法
  3.  
  4. def func():
  5. time.sleep(3)
  6.  
  7. if __name__ == '__main__':
  8. t = Thread(target=func)
  9. t.start()
  10. print(enumerate())
  11. print(active_count())
  12.  
  13. # [<_MainThread(MainThread, started 9212)>, <Thread(Thread-1, started 1612)>] 列表形式
  14. # 2
  15.  
  16. -------------------------------------
  17.  
  18. print(enumerate()[0].getName()) #enumerate()是一个列表,取索引值[0],再通过getName(),一样能拿到线程的名字
  19. print(current_thread().getName())
  20. #MainThread
  21. #MainThread

os.cpu_count()    查看cpu核数

  1. import os
  2. print(os.cpu_count())

线程池

t = ThreadPoolExecutor()    创建线程池的时候,如果不设置数量,默认是cpu核数*5

证明线程池不设置参数,默认值 是cpu核数*5

  1. import time
  2. import os
  3. from threading import ac-tive_count
  4. from concurrent.futures import ThreadPoolExecutor
  5.  
  6. def func():
  7. time.sleep(1)
  8.  
  9. if __name__ == '__main__':
  10. t = ThreadPoolExecutor() #创建线程池的时候,如果不设置数量,默认是cpu核数*5
  11. for i in range(100):
  12. t.submit(func,)
  13. print(os.cpu_count()) #cpu核数
  14. print(active_count()) #子线程数 + 主线程
  15.  
  16. #
  17. #21

进程池不要超过cpu核数的2倍(不是真理,具体会根据程序问题的增多,数目相应调大,也和电脑的性能有关)

这个参数肯定不能再程序里面写死,要写到配置文件里,要让软件的使用者( 给运维人员,不是直接给客户)根据他自己的业务场景以及他硬件的性能,要做相应的调整,取配置,所有的支

持并发的软件都是这样做,都应该这样做.不应该在程序里面写死.

多线程+异步调用+requests

requests 库

HTTP客户端库(编写爬虫和测试服务器响应数据时经常用到)

安装:pip install requests

get 请求:

  r = requets.get('http://www.baidu.com')

  r.text 返回headers中的编码解析的结果

异步调用:

  (回调机制:任务执行完,触发回调函数,同时把任务结果传给回调函数)

  提交完任务,(为该任务绑定一个回调函数),不用在原地等任务执行完毕拿到结果,可以直接提交下一个任务.

  一个任务一旦执行完毕就会自动触发回调函数的运行

不在原地等结果,那么结果哪里去了?

  就是通过回调机制

回调函数:add_done_callback(func)

  回调函数的参数是单一的:

  回调函数的参数就是它所绑定任务的返回值(绑定任务的return)

异步调用,不用等结果 结果去哪了 就是 回调

  1. import requests
  2. import time
  3. from threading import current_thread
  4. from concurrent.futures import ThreadPoolExecutor
  5.  
  6. url = ['https://www.baidu.com',
  7. 'https://www.jd.com',
  8. 'https://www.python.org',
  9. 'http://www.qq.com']
  10.  
  11. def get(url):
  12. print('get',current_thread().getName(),url) #current_thread().getName()打印哪些线程执行下载任务
  13. time.sleep(2)
  14. r = requests.get(url)
  15. if r.status_code == 200: # 200代表成功下载
  16. return {'url': url, 'text': r.text}
  17.  
  18. def parse(obj):
  19. res = obj.result()
  20. print('parse',current_thread().getName(),res['url'],len(res['text'])) #打印哪些线程执行解析任务
  21.  
  22. if __name__ == '__main__':
  23. t = ThreadPoolExecutor(2)
  24. for i in url:
  25. t.submit(get,i).add_done_callback(parse) #回调函数
  26. t.shutdown(wait=True)
  27. print(current_thread().getName())
  28.  
  29. # get ThreadPoolExecutor-0_0 https://www.baidu.com
  30. # get ThreadPoolExecutor-0_1 https://www.jd.com
  31. # parse ThreadPoolExecutor-0_0 https://www.baidu.com 2443
  32. # get ThreadPoolExecutor-0_0 https://www.python.org
  33. # parse ThreadPoolExecutor-0_1 https://www.jd.com 124541
  34. # get ThreadPoolExecutor-0_1 http://www.qq.com
  35. # parse ThreadPoolExecutor-0_1 http://www.qq.com 235464
  36. # parse ThreadPoolExecutor-0_0 https://www.python.org 48856
  37. # MainThread

一直是由线程控制处理

通过进程演示异步概念(不用开新的进程,主进程处理结果)

  1. import requests
  2. import time
  3. import os
  4. from threading import Thread, current_thread
  5. from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
  6.  
  7. url = ['https://www.baidu.com',
  8. 'https://www.jd.com',
  9. 'https://www.python.org',
  10. 'http://www.qq.com']
  11.  
  12. def get(url):
  13. print('get',os.getpid(),url) #os.getpid()打印哪些进程执行下载任务
  14. time.sleep(3)
  15. r = requests.get(url)
  16. if r.status_code == 200:
  17. return {'url': url, 'text': r.text}
  18.  
  19. def parse(obj):
  20. res = obj.result()
  21. print('parse',os.getpid(),res['url'],len(res['text'])) #os.getpid()打印哪些进程执行解析任务
  22.  
  23. if __name__ == '__main__':
  24. t = ProcessPoolExecutor(2)
  25. for i in url:
  26. t.submit(get,i).add_done_callback(parse)
  27. t.shutdown(wait=True)
  28. print('\n',os.getpid())
  29.  
  30. # get 6972 https://www.baidu.com
  31. # get 7180 https://www.jd.com
  32. # get 6972 https://www.python.org
  33. # parse 7856 https://www.baidu.com 2443
  34. # get 7180 http://www.qq.com
  35. # parse 7856 https://www.jd.com 124541
  36. # parse 7856 http://www.qq.com 235464
  37. # parse 7856 https://www.python.org 48856
  38. #
  39. #

线程&线程池的更多相关文章

  1. GIL 线程/进程池 同步异步

    GIL 什么是GIL 全局解释器锁,本质是一把互斥锁,是加在cpython解释器上的一把锁, 同一个进程内的所有线程需要先抢到GIL锁,才能执行python代码 为什么要有GIL cpython解释器 ...

  2. 常量,字段,构造方法 调试 ms 源代码 一个C#二维码图片识别的Demo 近期ASP.NET问题汇总及对应的解决办法 c# chart控件柱状图,改变柱子宽度 使用C#创建Windows服务 C#服务端判断客户端socket是否已断开的方法 线程 线程池 Task .NET 单元测试的利剑——模拟框架Moq

    常量,字段,构造方法   常量 1.什么是常量 ​ 常量是值从不变化的符号,在编译之前值就必须确定.编译后,常量值会保存到程序集元数据中.所以,常量必须是编译器识别的基元类型的常量,如:Boolean ...

  3. 子进程回收资源两种方式,僵尸进程与孤儿进程,守护进程,进程间数据隔离,进程互斥锁,队列,IPC机制,线程,守护线程,线程池,回调函数add_done_callback,TCP服务端实现并发

    子进程回收资源两种方式 - 1) join让主进程等待子进程结束,并回收子进程资源,主进程再结束并回收资源. - 2) 主进程 “正常结束” ,子进程与主进程一并被回收资源. from multipr ...

  4. C#线程 线程进阶

    第四部分:高级线程 非阻塞同步 前面我们说过,即使在分配或增加字段的简单情况下,也需要同步.尽管锁定始终可以满足此需求,但是竞争性锁定意味着线程必须阻塞,从而遭受上下文切换的开销和调度的延迟,这在高度 ...

  5. Linux线程的实现 & LinuxThread vs. NPTL & 用户级内核级线程 & 线程与信号处理

    另,线程的资源占用可见:http://www.cnblogs.com/charlesblc/p/6242111.html 进程 & 线程的很多知识可以看这里:http://www.cnblog ...

  6. Linux线程 之 线程 线程组 进程 轻量级进程(LWP)

    Thread Local Storage,线程本地存储,大神Ulrich Drepper有篇PDF文档是讲TLS的,我曾经努力过三次尝试搞清楚TLS的原理,均没有彻底搞清楚.这一次是第三次,我沉浸gl ...

  7. JAVA之旅(十五)——多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止

    JAVA之旅(十五)--多线程的生产者和消费者,停止线程,守护线程,线程的优先级,setPriority设置优先级,yield临时停止 我们接着多线程讲 一.生产者和消费者 什么是生产者和消费者?我们 ...

  8. python 进程和线程-线程和线程变量ThreadLocal

    线程 线程是由若干个进程组成的,所以一个进程至少包含一个线程:并且线程是操作系统直接支持的执行单元.多任务可以由多进程完成,也可由一个进程的多个线程来完成 Python的线程是真正的Posix Thr ...

  9. 进程?线程?多线程?同步?异步?守护线程?非守护线程(用户线程)?线程的几种状态?多线程中的方法join()?

    1.进程?线程?多线程? 进程就是正在运行的程序,他是线程的集合. 线程是正在独立运行的一条执行路径. 多线程是为了提高程序的执行效率.2.同步?异步? 同步: 单线程 异步: 多线程 3.守护线程? ...

  10. 关于Spring事务的原理,以及在事务内开启线程,连接池耗尽问题.

    主要以结果为导向解释Spring 事务原理,连接池的消耗,以及事务内开启事务线程要注意的问题. Spring 事务原理这里不多说,网上一搜一大堆,也就是基于AOP配合ThreadLocal实现. 这里 ...

随机推荐

  1. COGS 1361. 树

    ★   输入文件:treed.in   输出文件:treed.out   简单对比时间限制:1 s   内存限制:128 MB [问题描述] 在一个凉爽的夏夜,xth和rabbit来到花园里砍树.为啥 ...

  2. 洛谷 P1216 [USACO1.5]数字三角形 Number Triangles(水题日常)

    题目描述 观察下面的数字金字塔. 写一个程序来查找从最高点到底部任意处结束的路径,使路径经过数字的和最大.每一步可以走到左下方的点也可以到达右下方的点. 7 3 8 8 1 0 2 7 4 4 4 5 ...

  3. 在Oracle用SQL处理以 System.currentTimeMillis

    有時為了系統的需求會紀錄到毫秒(Millisecond),我們會接將得到的值寫入db,但是如果要用SQL 做時間範圍的搜尋,有以下做法( systemdate欄位存放System.currentTim ...

  4. jquery.placeholder.min.js让吃屎的IE浏览器支持placeholder去吧

    描述:现在都是HTML5时代了,所有的浏览器都支持placeholder,唯独IE不支持.现在我们有了这款插件,IE下终于可以支持了!  图片展示:   兼容浏览器:IE6+/Firefox/Goog ...

  5. Qt 之 QApplication

    1.QApplication QApplication类管理GUI程序的控制流和主要设置,是基于QWidget的,为此特化了QGuiApplication的一些功能,处理QWidget特有的初始化和结 ...

  6. 判断请求是否为ajax

    判断请求是否为ajax 转载:http://www.cnblogs.com/tony-jingzhou/archive/2012/07/30/2615612.html x-requested-with ...

  7. 一个小笔记(2):Socket网络编程

    网络通信的流程: 服务器端申请套接字 -> 绑定套接字到本地,打开端口 -> 监听端口 -> 等待接受消息 -> 有消息之后,读取消息 客户端申请套接字 -> 向服务端发 ...

  8. postman使用--环境变量

    变量 postman提供了变量设置,有四种变量类型本地变量全局变量环境变量 数据变量 什么是环境变量 环境变量指在不同环境,同一个变量值随着环境不同而变化,比如在测试环境时,host为:dev.pos ...

  9. 遇到的django问题

    问题1: No migrations to apply 删除了migrations中0001_initial.py文件,重新执行 python manage.py makemigrations pyt ...

  10. loj6063 Shadow

    题目描述 题解: 显然凸多面体投下来一定是个凸多边形. 对于$30$分,直接投到$x-y$平面上即可. 对于$100$分,考虑搞出平面的一般式方程$ax+by+cz+d=0$. 给出平面上三个点$A, ...