线程的概念

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

三 线程与进程的区别

1

1.线程的创建开销小(无需申请内存空间或者资源),创建线程的速度快,(但是不能无限开)

2.同一个进程下的多个线程,共享该进程地址空间的资源(数据等内容)

3.改变线程,会影响其他线程(在同一个进程的内存空间内的线程)  但是改变主进程,不会影响子进程

  1. Threads share the address space of the process that created it; processes have their own address space.
  2. 进程分享创建他的留给他们的地址空间,而进程们却又自己的地址空间
  3. Threads have direct access to the data segment of its process; processes have their own copy of the data segment of the parent process.
  4. 线程直接访问进程的数据段;进程拥有父进程的数据段的自身副本。
  5. Threads can directly communicate with other threads of its process; processes must use interprocess communication to communicate with sibling processes.
  6. New threads are easily created; new processes require duplication of the parent process.
  7. Threads can exercise considerable control over threads of the same process; processes can only exercise control over child processes.
  8. Changes to the main thread (cancellation, priority change, etc.) may affect the behavior of the other threads of the process; changes to the parent process does not affect child processes.

四 为何要用多线程

  多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。详细的讲分为4点:

  1. 多线程共享一个进程的地址空间

2. 线程比进程更轻量级,线程比进程更容易创建可撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用

3. 若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。

4. 在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(这一条并不适用于python)

启线程的两种方式

与开启进程的方式类似

from threading import Thread
def piao(name,n):
print('%s is piaoing %s and%s'%(name,n,os.getpid())) if __name__ == '__main__':
t=Thread(target=piao,args=('alex',11,)) #这里的写法要注意,
t.start()
print('zhu')

常用方式,

from threading import Thread
import os
class Piao(Thread):
def __init__(self,name):
super(Piao, self).__init__()
self.name=name
def run(self): # 方法名一定要写成RUN 的形式否则不行
print('%s is piaoing'%self.name) if __name__ == '__main__':
t=Piao('alex')
t.start() print('主')

利用类的继承开启线程,不太常用,但是要会

六 守护线程

无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁

需要强调的是:运行完毕并非终止运行

#1.对主进程来说,运行完毕指的是主进程代码运行完毕

#2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕

详细解释:

#1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束,

#2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,
而进程必须保证非守护线程都运行完毕后才能结束。

线程池:与进程池概念类似(引入进程池模块就可以了,无须再引入Thread模块)

池的目的:当有很大的工作量需要去完成的时候,需要限制每次进入线程(或者进程)的数量。

from concurrent.futures import ThreadPoolExecutor  #引入线程池模块
def piao(name):
print('%s is piao ing '%name) if __name__ == '__main__':
t=ThreadPoolExecutor(4) #
objs=[]
for i in range(10):
obj=t.submit(piao,'alex')
objs.append(obj)
t.shutdown(wait=True)
for obj in objs:
print(obj.result())
print('zhu')

进程池

  1. 很明显需要并发执行的任务通常要远大于核数
  2. 一个操作系统不可能无限开启进程,通常有几个核就开几个进程
  3. 进程开启过多,效率反而会下降(开启进程是需要占用系统资源的,而且开启多余核数目的进程也无法做到并行)

ps:对于远程过程调用的高级应用程序而言,应该使用进程池,Pool可以提供指定数量的进程,供用户调用,当有新的请求提交到pool中时,

如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到规定最大值,那么该请求就会等待,

直到池中有进程结束,就重用进程池中的进程。

from concurrent.futures import ProcessPoolExecutor
import os,time
n=100
def piao(name):
print('%s is piaoing'%name,os.getpid())
time.sleep(1)
global n
return n**2
if __name__ == '__main__':
p=ProcessPoolExecutor(4)
objs=[]
for i in range(10):
obj=p.submit(piao,i)
objs.append(obj)
p.shutdown(wait=True)
for obj in objs:
print(obj.result())
print('zhu',os.getpid())
打印结果如下:: 可以看到四个进程的进程ID 都是固定的,这就是进程池,当当前进程完成后进入下一个进程,此时还是用的这些进程ID
证明进程池是开

0 is piaoing 1348
1 is piaoing 14076
2 is piaoing 13816
3 is piaoing 13756

4 is piaoing 1348
5 is piaoing 14076
6 is piaoing 13816
7 is piaoing 13756

8 is piaoing 1348
9 is piaoing 14076


 t.submit(func1,obj).add_done_callback(函数名)   回调函数

from concurrent.futures import ThreadPoolExecutor
import time
from threading import current_thread
import requests #模拟浏览器,走HTTP协议发送请求,模块下载网页
def func1(url):
print('%s GET %s'%(current_thread().getName(),url)) #得到当前线程的名称
response=requests.get(url) #得到网页内容
time.sleep(3)
if response.status_code==200: #status_code response的返回的状态码,当为200时才表示下载成功
return{'url':url,'text':response.text}#response.text 得到下载的内容
def res(obj):
ret=obj.result()
print('[%s]<%s> %s'%(current_thread().getName(),ret['url'],len(ret['text']))) if __name__ == '__main__':
t=ThreadPoolExecutor(2)
urllis=[
'https://www.jd.com',
'https://www.tmall.com',
'https://www.baidu.com',
'https://www.douban.com'
]
for url in urllis:
t.submit(func1,url).add_done_callback(res) #回调函数,将函数func1执行的结果返回给res,
#在res中用 .result()的方式来取出返回值
t.shutdown(wait=True)
print('zhu')
import struct
a=struct.pack('i',11111)
print(a)
for i in a:
print(bin(i))
print(bin(11111))

day33 python学习 多线程的更多相关文章

  1. Python学习——多线程,异步IO,生成器,协程

    Python的语法是简洁的,也是难理解的. 比如yield关键字: def fun(): for i in range(5): print('test') x = yield i print('goo ...

  2. python学习-多线程并发

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

  3. python学习笔记- 多线程(1)

    学习多线程首先先要理解线程和进程的关系. 进程 计算机的程序是储存在磁盘中的可执行的二进制文件,执行时把这些二进制文件加载到内存中,操作系统调用并交给处理器执行对应操作,进程是程序的一次执行过程,这是 ...

  4. Python学习笔记(三)多线程的使用

    这节记录学习多线程的心得.   Python提供了thread模块,不过该模块的缺点很多,例如无法方便的等待线程结束,所以我们使用更加高级的threading模块.   threading模块的使用一 ...

  5. python学习笔记-(十三)线程&多线程

    为了方便大家理解下面的知识,可以先看一篇文章:http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html 线程 1.什么是线程? ...

  6. python学习笔记(二十九)为什么python的多线程不能利用多核CPU

    问题:为什么python的多线程不能利用多核CPU,但是咱们在写代码的时候,多线程的确是在并发,而且还比单线程快原因:因为GIL,python只有一个GIL,运行python时,就要拿到这个锁才能执行 ...

  7. python学习笔记(二十七)多线程与多进程

    线程是程序里面的最小执行单元. 进程是资源的集合. 线程是包含在一个进程里面,一个进程可以有多个线程,一个进程里面默认有一个主线程.由主线程去启动子线程. 1.多线程 import threading ...

  8. python学习笔记之使用threading模块实现多线程(转)

    综述 Python这门解释性语言也有专门的线程模型,Python虚拟机使用GIL(Global Interpreter Lock,全局解释器锁)来互斥线程对共享资源的访问,但暂时无法利用多处理器的优势 ...

  9. Python学习之路14☞多线程与多进程

    一 进程与线程的概念 1.1 进程 进程定义: 进程就是一个程序在一个数据集上的一次动态执行过程.进程一般由程序.数据集.进程控制块三部分组成.我们编写的程序用来描述进程要完成哪些功能以及如何完成:数 ...

随机推荐

  1. English trip -- Review Unit1 Personal Information 个人信息

    1.重点内容进行自我介绍 What's you name? I'm Loki Where are you from? I'm Local, I'm Chengdu How old are you? t ...

  2. MSSQL 一坑 SQL Management Studio 管理工具的快捷方式被删掉了

    如果确定已经安装的情况下,到这里去找下吧(我这里用的是sql 2008) C:\Program Files\Microsoft SQL Server\100\Tools\Binn\VSShell\Co ...

  3. GetImageURL

    Sub GetImageUrl(ByVal URL As String) Dim strText As String Dim i As Long Dim OneImg With CreateObjec ...

  4. php--------ThinkPHP3.2验证码使用

    Thinkphp框架验证码的路径目录:ThinkPHP -> Library -> Think -> Verify.class.php ,只要在控制器中实例化这个类就能实现验证码的功 ...

  5. The Architecture of Open Source Applications——阅读笔记part 1

    Architects look at thousands of buildings during their training, and study critiques of those buildi ...

  6. PatePoco中对sql参数化时Top参数化的问题

    PatePoco中对sql参数化是直接用@+参数名来处理,但是想用如下语句时竟然报错了 SELECT TOP @num * FROM tableA 执行时抛出异常,根据错误提示搞了很久都没找到原因,最 ...

  7. javascript的replace之正则表达式的浅析

    在javascript中,字符串的replace方法可以指定替换某些字符串. 1.直接替换字符串 "yy/MM/dd".replace("yy","2 ...

  8. LeetCode OJ:Valid Number

    Validate if a given string is numeric. Some examples:"0" => true" 0.1 " => ...

  9. DevExpress v18.1新版亮点——WinForms篇(一)

    用户界面套包DevExpress v18.1日前正式发布,本站将以连载的形式为大家介绍各版本新增内容.本文将介绍了DevExpress WinForms v18.1 的新功能,快来下载试用新版本! C ...

  10. Bitdefender Internet Security 2013 – 免费3个月

    Bitdefender Internet Security 2013 – 免费3个月大约1分钟参加调查,申请3个月免费,缺陷是…要经过人工审核活动地址: 点此进入申请方法,最好用谷歌翻译(俄文)