1、进程与线程优、缺点的比较
总言:使用进程和线程的目的,提高执行效率。

进程:

  优点:能利用机器的多核性能,同时进行多个操作。

  缺点:需要耗费资源,重新开辟内存空间,耗内存。

线程:

  优点:共享内存(资源),做IO操作时,可以创造并发操作。

  缺点:抢占资源。

总结:进程并不是越多越好,最好CPU个数 = 进程个数。

   线程也并不是越多越好,应根据业务需求来确定个数,因为请求上下文切换非常耗时。

2、适用情况
IO密集型(不用CPU) :适合多线程

计算密集型(要用CPU):适合多进程

3、线程
  (1)线程的创建(threading模块)
import threading #导入该模块
import time

def f0():
pass

def f1(a1,a2):
time.sleep(1)
print(a1,a2)
f0()

#创建子线程,任务为f1(),参数为args的元祖
t = threading.Thread(target=f1,args=(123,456,))
#默认setDaemon为false,主线程要等待子线程执行完毕后再结束
#设置为True后,就不等待
t.setDaemon(True)
t.start() #告诉线程我们准备好了

(2)主线程是否等待子线程

  t.setDaemon(True/False)

  用于设置主线程执行完毕后,是否等待子线程,默认为false,要等待。

  (3)主线程是否等待某个子线程执行完毕

  t.join()  一直等待

  t.join(2)最多等待该子线程2s

(4)线程锁RLock

  避免因并发操作而造成脏数据,线程锁能锁住全部子线程,同一时刻允许一个线程执行操作。

#未使用线程锁时
import threading
import time

gl_num = 0

def show(arg):
global gl_num
time.sleep(0.5)
gl_num +=1
print(gl_num)

#开了10个线程,同时都对全局变量gl_num进行操作
for i in range(10):
t = threading.Thread(target=show, args=(i,))
t.start()

print('main thread stop')

#使用了线程锁时
import threading
import time

gl_num = 0

lock = threading.RLock() #创建锁

def Func():
lock.acquire() #锁定
global gl_num
gl_num += 1
time.sleep(0.25)
print(gl_num)
lock.release() #释放锁

for i in range(10):
t = threading.Thread(target=Func)
t.start()
print('main thread stop')

(5)事件(Event)

python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法 set、wait、clear。

事件处理的机制:全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

  event.wait()  等待绿灯开启,再继续执行

  event.clear()设为红灯

  event.set()   设为绿灯

import threading

def do(event):
print('start')
event.wait() #阻塞住,等待绿灯。event_obj.set()语句执行后,又回来继续执行下一句
print('execute')

event_obj = threading.Event()
for i in range(3):
t = threading.Thread(target=do, args=(event_obj,))
t.start()

event_obj.clear() #设为红灯
inp = input('input:')
if inp == 'true':
event_obj.set() #设为绿灯

(6)生产者消费者模型、队列(先进先出)(queue模块)

4、进程
(1)创建进程(multiprocessing模块)

import multiprocessing
import time

def f1(a1):
time.sleep(3)
print(a1)

if __name__ == '__main__': #Windows上,进程语句必须放在main里面
#创建进程,任务为执行f1(),参数为11,由元祖封装
t = multiprocessing.Process(target=f1,args=(11,))
# 当daemon设为true时,主进程结束后就不再等待子进程了,默认为false要等待
t.daemon = True #所以结果没有打印出 11
t.start()

t = multiprocessing.Process(target=f1,args=(22,))
t.start()
print('end')

(2)主进程是否等待子进程

  t.setDaemon(True/False)

  用于设置主进程执行完毕后,是否等待子进程,默认为false,要等待。

 (3)主进程是否等待某个子进程执行完毕

  t.join() 一直等待

  t.join(2)最多等待该子进程2s

  (4)线程与进程,数据之间是否共享对比
  默认每个进程之间的数据是不共享的,各做各的。

  而每个线程之间的数据是共享的。 
#进程操作时,数据是不共享的
from multiprocessing import Process

li = []
def foo(i):
li.append(i)
print('say hi',li)

if __name__ == '__main__':
for i in range(10):
p = Process(target=foo,args=(i,))
p.start()

线程处理时,数据是共享的,将process改为thread,结果为:

(5)特殊的数据容器
  如果想要多个进程同时操作一份数据,则需要特殊的容器。

  方法一:Array数组(不推荐)

    a.创建时需要规定大小,切不能改变。

    b.内部数据必须统一为相同类型,字符串、数字等。

  方法二:manager.dict()共享数据(推荐)

    创建: m = Manager()

       dict = m.dict()
from multiprocessing import Process,Manager

def Foo(i,dic):
dic[i] = 100+i
print(len(dic))

# for k,v in dic.items():
# print(k,v)
if __name__ == '__main__':
manager = Manager()
dic = manager.dict()
# dic = {} #dic为普通字典时,返回值为 1 1

for i in range(2):
p = Process(target=Foo,args=(i,dic))
p.start()
p.join()

(6)进程池(python中已创建好) pool

from multiprocessing import Pool
import time

def f1(a1):
time.sleep(1)
print(a1)
return 1000

def f2(arg):
print(arg)

if __name__ == '__main__':

pool = Pool(5)
# pool.apply(f1,(2,))
for i in range(10):
pool.apply_async(func=f1, args=(i,), callback=f2)#特别注意args跟的参数为元祖类型
#callback=f2表示回调函数,将f1 return的值作为参数传给f2
pool.close()
pool.join()#等待子进程执行完

pool.apply()和pool.apply_async()对比:
pool.apply() :每一个任务都是排队执行的,内部有join()方法,会等待子进程
pool.apply_async():每一个任务都是并发执行,且可以设置回调函数,内部无join()方法,
进程deamon = true,不等待子进程,要想等待子进程,需先pool.close(),再pool.join()

5、协程(高性能代名词)

线程和进程的操作时程序出发系统接口,最后的执行者是系统,协程的操作则是程序员。

存在意义:只使用一个线程,在一个线程中规定某个代码块执行顺序。
适用于: IO密集型操作

方法一:greenlet模块
    需手动切换任务(不推荐)

方法二:gevent模块(本质也是基于greenlet)
    自动切换任务,谁先回来就先处理谁(推荐)
import gevent

def foo():
print('1')
gevent.sleep(0) #切换标志
print('2')

def bar():
print('3')
gevent.sleep(0) #切换标志
print('4')

gevent.joinall([
gevent.spawn(foo),
gevent.spawn(bar),
])

python 线程 进程的更多相关文章

  1. python 线程 进程 协程 学习

    转载自大神博客:http://www.cnblogs.com/aylin/p/5601969.html 仅供学习使用···· python 线程与进程简介 进程与线程的历史 我们都知道计算机是由硬件和 ...

  2. python线程进程

    多道技术: 多道程序设计技术 所谓多道程序设计技术,就是指允许多个程序同时进入内存并运行.即同时把多个程序放入内存,并允许它们交替在CPU中运行,它们共享系统中的各种硬.软件资源.当一道程序因I/O请 ...

  3. Python 线程&进程与协程

    Python 的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆为了在阿姆斯特丹打发时间,决心开发一个新的脚本解释程序,作为ABC语言的一种继承.Py ...

  4. python 线程进程

      一 线程的2种调用方式 直接调用 实例1: import threading import time def sayhi(num): #定义每个线程要运行的函数 print("runni ...

  5. python线程,进程,队列和缓存

    一.线程 threading用于提供线程相关的操作,线程是应用程序中工作的最小单元. 创建线程的两种方式1.threading.Thread import threading def f1(arg): ...

  6. python 线程,进程28原则

    基于函数实现 from threading import Thread def fun(data, *args, **kwargs): """ :param data: ...

  7. python 线程/进程模块

    线程的基本使用: import threading # ###################### 1.线程的基本使用 def func(arg): print(arg) t = threading ...

  8. python 线程 进程 标识

    s = '%s%s%s%s%s%s%s%s' % ( time.strftime('%Y%m%d %H:%M:%S', time.localtime(time.time())), ' os.getpp ...

  9. python 线程(一)理论部分

    Python线程 进程有很多优点,它提供了多道编程,可以提高计算机CPU的利用率.既然进程这么优秀,为什么还要线程呢?其实,仔细观察就会发现进程还是有很多缺陷的. 主要体现在一下几个方面: 进程只能在 ...

随机推荐

  1. 【Hadoop 分布式部署 六:环境问题解决和集群基准测试】

    环境问题: 出现Temporary  failure  in  name  resolutionp-senior-zuoyan.com 的原因有很多,主要就是主机没有解析到, 那就在hadoop的sl ...

  2. BZOJ 2648 SJY摆棋子(KD Tree)

    http://www.lydsy.com/JudgeOnline/problem.php?id=2648 题意: 思路: KDtree模板题. 参考自http://www.cnblogs.com/ra ...

  3. 用Let's Encrypt实现Https(Windows环境+Tomcat+Java)

    补充1: 已解决20的部分问题,移步这里 单域名下多子域名同时认证HTTPS 补充2: 之前忘了说了,我这个方法只对Tomcat7.0以上有用(要不然就是8.0...) 我自己用的是9.0 原因好像是 ...

  4. 【Django】Django-REST-Framework

    [创建简单的API] 1. cmd.exe >django-admin startproject django_rest>cd django_rest\django_rest>pyt ...

  5. 阿里云CentOS Linux服务器上搭建邮件服务器遇到的问题

    参考文章: 阿里云CentOS Linux服务器上用postfix搭建邮件服务器 Linux系统下邮件服务器的搭建(Postfix+Dovecot) 本来想自己搭建邮件服务器,但是看到一篇资料表示阿里 ...

  6. sql 中常见的控制流语句

    控制流语句:1 begin .....end  2 if ...else  例如:if exists (select * from 表名称 ) begin selct * from  表名称 end  ...

  7. 【C#】采用OleDB读取Excel文件转DataTable

    using System; using System.Data; using System.Data.OleDb; using System.IO; using System.Linq; using ...

  8. hadoop中 bin/hadoop fs -ls ls: `.': No such file or directory问题

    2.x版本上的使用bin/hadoop fs -ls  /就有用 应该使用绝对路径就不会有问题 mkdir也是一样的 原因:-ls默认目录是在hdfs文件系统的/user/用户名(用户名就命令行@符号 ...

  9. java开发手册(阿里巴巴)——编程规约(部分)

    (一)命名风格 3. [强制]类名使用 UpperCamelCase 风格,但以下情形例外:DO / BO / DTO / VO / AO / PO / UID 等. 正例:MarcoPolo / U ...

  10. 学习笔记19—dpabi错误集

    1.回归斜边量的时候千万不要用红色标记的地方,而要用紫色标记的地方