python并发之多线程
一开启线程的两种方式
from threading import Thread
import time
def haha(name):
time.sleep(2)
print('%s 你大爷......'%name) if __name__ == '__main__':
t=Thread(target=haha,args=('一根',))
t.start()
t.join()
print('主')
from threading import Thread
import time
def jiji(eat):
time.sleep(1)
print('%s 富贵,你吃了什么???'%eat)
if __name__ == '__main__':
time.sleep(2)
t=Thread(target=jiji,args=('屎',)) t.start()
print('主')
方式一
from threading import Thread
import time
class hh(Thread):
def __init__(self,name):
super().__init__()
self.name=name def play(self):
time.sleep(2)
print('%s basket-ball......'%self.name)
if __name__ == '__main__':
t=hh('王浩')
t.start()
print('主线程')
方式二
二在一个进程下开启多个线程与在一个进程下开启多个子进程的区别
from multiprocessing import Process
from threading import Thread
import os def work():
print('hello') if __name__ == '__main__':
#在主线程下来气进程
t=Thread(target=work)
t.start()
print('主线程/主进程') '''
打印结果:
hello
主线程/主进程
''' #在主进程下开启子进程
t=Process(target=work)
t.start()
print('主线程/主进程') '''
打印结果:
主线程/主进程
hello
'''
子线程比子进程打印的快
from multiprocessing import Process
from threading import Thread
import os
def work():
print('hello',os.getpid())
if __name__ == '__main__': #part1:在主进程下开启多个线程,每个线程都和主进程的pid一样
t1=Thread(target=work)
t2=Thread(target=work)
t1.start()
t2.start()
print('主线程/主进程pid',os.getpid()) #part2:开启多个进程,每个进程都有着不同的pid
p1=Process(target=work)
p2=Process(target=work)
p1.start()
p2.start()
print('主线程/主进程pid',os.getpid())
pid
from threading import Thread
from multiprocessing import Process
import os
def work():
global n
n=0 if __name__ == '__main__':
n=100
p=Process(target=work)
p.start()
p.join()
print('主',n) #毫无疑问子进程p已经将自己的全局的n改成了0,当改的仅仅是他自己的,父进程n任然是100 n=1
t=Thread(target=work)
t.start()
t.join()
print('主',n)#查看结果为0,因为同一进程内的线程之间共享进程内的数据
同一进程内的线程共享该进程的数据
三练习
import multiprocessing
import threading import socket
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(('127.0.0.1',8080))
s.listen(5) def action(conn):
while True:
data=conn.recv(1024)
print(data)
conn.send(data.upper()) if __name__ == '__main__': while True:
conn,addr=s.accept() p=threading.Thread(target=action,args=(conn,))
p.start() 多线程并发的socket服务端
多线程并发的socket服务端
import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('127.0.0.1',8080)) while True:
msg=input('>>: ').strip()
if not msg:continue s.send(msg.encode('utf-8'))
data=s.recv(1024)
print(data)
客户端
2三个任务,一个接收用户输入,一个将用户输入的内容格式化成大写,一个将格式化后的结果存入文件
from threading import Thread
msg_l=[]
format_l=[]
def talk():
while True:
msg=input('>>: ').strip()
if not msg:continue
msg_l.append(msg) def format_msg():
while True:
if msg_l:
res=msg_l.pop()
format_l.append(res.upper()) def save():
while True:
if format_l:
with open('db.txt','a',encoding='utf-8') as f:
res=format_l.pop()
f.write('%s\n' %res) if __name__ == '__main__':
t1=Thread(target=talk)
t2=Thread(target=format_msg)
t3=Thread(target=save)
t1.start()
t2.start()
t3.start()
四线性相关其他知识
Thread实例对象的方法
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。 threading模块提供的一些方法:
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前
终止后的线程。
hreading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
from threading import Thread
import threading
from multiprocessing import Process
import os def work():
import time
time.sleep(3)
print(threading.current_thread().getName()) if __name__ == '__main__':
#在主进程下开启线程
t=Thread(target=work)
t.start() print(threading.current_thread().getName())
print(threading.current_thread()) #主线程
print(threading.enumerate()) #连同主线程在内有两个运行的线程
print(threading.active_count())
print('主线程/主进程') '''
打印结果:
MainThread
<_MainThread(MainThread, started 140735268892672)>
[<_MainThread(MainThread, started 140735268892672)>, <Thread(Thread-1, started 123145307557888)>]
主线程/主进程
Thread-1
'''
主线程等待子线程结束
from threading import Thread
import time
def sayhi(name):
time.sleep(2)
print('%s say hello' %name) if __name__ == '__main__':
t=Thread(target=sayhi,args=('egon',))
t.start()
t.join()
print('主线程')
print(t.is_alive())
'''
egon say hello
主线程
False
'''
五守护线程
无论进程还是线程,都是守护主进程运行结束后自动销毁,那么运行接受又是在那种情况下的呢?
1主进程在其代码结束后就算运行结束了(守护进程就会被销毁),主进程就会等待非守护的子进程运行结束后回收其资源,才会结束。
2主线程在其他非守护进程完毕后才算完(守护进程被销毁),主线程结束意味着进程结束,进程整体资源被回收,所以主线程必须在其他线程结束后才结束
from threading import Thread
import time
def sayhi(name):
time.sleep(2)
print('%s say hello' %name) if __name__ == '__main__':
t=Thread(target=sayhi,args=('egon',))
t.setDaemon(True) #必须在t.start()之前设置
t.start() print('主线程')
print(t.is_alive())
'''
主线程
True
'''
from threading import Thread
import time
def foo():
print(123)
time.sleep(1)
print("end123") def bar():
print(456)
time.sleep(3)
print("end456") t1=Thread(target=foo)
t2=Thread(target=bar) t1.daemon=True
t1.start()
t2.start()
print("main-------") 迷惑人的例子
有点挖坑的意思哦
六 Python GIL(Global Interpreter Lock)
定义:
在CPython中,全局解释器锁是一个互斥锁,它可以防止多个对象的出现。
本地线程同时执行Python的一组语言。这个锁是主要的
因为CPython的内存管理不是线程安全的。(然而,由于吉尔
存在,其他的特性已经发展到依赖于它所执行的保证。)
结论:在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势。
1. 多cpu,意味着可以有多个核并行完成计算,所以多核提升的是计算性能
2. 每个cpu一旦遇到I/O阻塞,仍然需要等待,所以多核对I/O操作没什么用处
结论:
对计算来说,cpu越多越好,但是对于I/O来说,再多的cpu也没用
当然对运行一个程序来说,随着cpu的增多执行效率肯定会有所提高(不管提高幅度多大,总会有所提高),这是因为一个程序基本上不会是纯计算或者纯I/O,所以我们只能相对的去看一个程序到底是计算密集型还是I/O密集型。
#分析:
我们有四个任务需要处理,处理方式肯定是要玩出并发的效果,解决方案可以是:
方案一:开启四个进程
方案二:一个进程下,开启四个线程 #单核情况下,分析结果:
如果四个任务是计算密集型,没有多核来并行计算,方案一徒增了创建进程的开销,方案二胜
如果四个任务是I/O密集型,方案一创建进程的开销大,且进程的切换速度远不如线程,方案二胜 #多核情况下,分析结果:
如果四个任务是计算密集型,多核意味着并行计算,在python中一个进程中同一时刻只有一个线程执行用不上多核,方案一胜
如果四个任务是I/O密集型,再多的核也解决不了I/O问题,方案二胜 #结论:现在的计算机基本上都是多核,python对于计算密集型的任务开多线程的效率并不能带来多大性能上的提升,甚至不如串行(没有大量切换),但是,对于IO密集型的任务效率还是有显著提升的。
from multiprocessing import Process
from threading import Thread
import os,time
def work():
res=0
for i in range(100000000):
res*=i if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为4核
start=time.time()
for i in range(4):
p=Process(target=work) #耗时5s多
p=Thread(target=work) #耗时18s多
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
计算密集型:多进程效率高
from multiprocessing import Process
from threading import Thread
import threading
import os,time
def work():
time.sleep(2)
print('===>') if __name__ == '__main__':
l=[]
print(os.cpu_count()) #本机为4核
start=time.time()
for i in range(400):
# p=Process(target=work) #耗时12s多,大部分时间耗费在创建进程上
p=Thread(target=work) #耗时2s多
l.append(p)
p.start()
for p in l:
p.join()
stop=time.time()
print('run time is %s' %(stop-start))
I/O密集型:多线程效率高
应用:
多线程用于IO密集型,如socket,爬虫,web
多进程用于计算密集型,如金融分析
python并发之多线程的更多相关文章
- python高级之多线程
python高级之多线程 本节内容 线程与进程定义及区别 python全局解释器锁 线程的定义及使用 互斥锁 线程死锁和递归锁 条件变量同步(Condition) 同步条件(Event) 信号量 队列 ...
- python 类变量 在多线程下的共享与释放问题
最近被多线程给坑了下,没意识到类变量在多线程下是共享的,还有一个就是没意识到 内存释放问题,导致越累越大 1.python 类变量 在多线程情况 下的 是共享的 2.python 类变量 在多线程情况 ...
- python中的多线程【转】
转载自: http://c4fun.cn/blog/2014/05/06/python-threading/ python中关于多线程的操作可以使用thread和threading模块来实现,其中th ...
- Python之FTP多线程下载文件之分块多线程文件合并
Python之FTP多线程下载文件之分块多线程文件合并 欢迎大家阅读Python之FTP多线程下载系列之二:Python之FTP多线程下载文件之分块多线程文件合并,本系列的第一篇:Python之FTP ...
- Python之FTP多线程下载文件之多线程分块下载文件
Python之FTP多线程下载文件之多线程分块下载文件 Python中的ftplib模块用于对FTP的相关操作,常见的如下载,上传等.使用python从FTP下载较大的文件时,往往比较耗时,如何提高从 ...
- Python系列之多线程、多进程
线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程. Python的标准库提供 ...
- Python 简单理解多线程
进程,是一个或多个线程的集合,每个进程在内存中是相对独立的. 线程,是计算机最小的运算单元,每个进程至少要有一个线程,多个线程时,每个线程间之间共享内存. 分别举例常规运行和多线程运行: 0)常规运行 ...
- python中的多线程
一个程序可以理解为一个进程,这个进程有其代号,可以依据这个代号将其杀死. 一个进程肯定有且只有一个主线程,他可以有很多子线程. 运行一个任务如果可以有许多子线程同时去做,当然会提高效率. 但是,在py ...
- python单线程,多线程和协程速度对比
在某些应用场景下,想要提高python的并发能力,可以使用多线程,或者协程.比如网络爬虫,数据库操作等一些IO密集型的操作.下面对比python单线程,多线程和协程在网络爬虫场景下的速度. 一,单线程 ...
随机推荐
- python glob fnmatch 用于文件查找操作
參考: http://python.jobbole.com/81552/:Python模块学习:glob文件路径查找 http://blog.csdn.net/suiyunonghen/article ...
- Python 练习冊,每天一个小程序
Python 练习冊,每天一个小程序 说明: Github 原文地址: 点击打开链接 Python 练习冊.每天一个小程序.注:将 Python 换成其它语言,大多数题目也试用 不会出现诸如「 ...
- oracle 10g下范围分区扫描的几种方式
oracle 10g下有几种扫描方式,注意最后一种扫描方式,当对分区的列进行计算时,会不走分区.这跟对索引列进行计算会导致无法用索引一样. --扫描单个分区 PARTITION RANGE SING ...
- ITM事件直接接收并解析
之前在实施一个监控项目时.客户由于买了IBM的小机.当前就赠送了TIVOLI的系统监控软件一套,客户也在他们的生产环境中部署了ITM的监控.由于没有购买IBM的netcool,无法集中管理告警事件,请 ...
- poj:4091:The Closest M Points
poj:4091:The Closest M Points 题目 描写叙述 每到饭点,就又到了一日几度的小L纠结去哪吃饭的时候了.由于有太多太多好吃的地方能够去吃,而小L又比較懒不想走太远,所以小L会 ...
- Springboot的默认定时任务——Scheduled注解
本博客参考博文地址. 1.pom依赖: 引入springboot starter包即可 <dependencies> <dependency> <groupId>o ...
- FiddlerCoreAPI开发(二)截获HTTPS流量
上一篇文章简单简单分析了fiddlercore自带样例的代码,本篇文章进入主题,介绍如何使用fiddlercore截获HTTPS流量. 当时学习完样例代码后,我觉得结合注释来抓HTTPS的包应该也很简 ...
- 3.更改ssh服务远程登录的配置
- .NET开发一个微信跳一跳辅助程序
昨天微信更新了,出现了一个小游戏"跳一跳",玩了一下 赶紧还蛮有意思的 但纯粹是拼手感的,玩了好久,终于搞了个135分拿了个第一名,没想到过一会就被朋友刷下去了,最高的也就200来 ...
- k-近邻算法实例
1. 简单例子 步骤 1.1 计算已知点和被求点的距离 1.2 按距离递增排序 1.3 求出距离最近的前k个点的类别最大值作为目标分类 from numpy import * import opera ...