线程依赖于进程,协程依赖于线程,效率最好的是协程,其次到线程,再到进程。总结:单线程会阻塞,协程不会阻塞。主要看会不会阻塞,其次看耗不耗资源。对比之下协程是最好的。
主线程结束,子线程才会结束。程序和进程通俗来讲就是一个运行一个不运行,不运行的叫程序,运行起来的叫进程。程序只有一个,但是进程可以有多个,即是一个程序可以对应多个进程。进程是一个拥有资源的地方。资源是一个资源分配的地方。如一个qq,你运行起来,就是一个进程,就可以让操作系统去调度,让它拥有操作摄像头,鼠标,键盘等功能。
从线程和进程的角度来说,进程是资源分配的最小单位,线程是独立调度的最小单位。
同一个进程中的多个线程之间可以并发执行,他们共享进程资源。
线程不拥有资源,线程可以访问隶属进程的资源,进程有自己的独立空间地址,线程没有自己的独立空间地址,但是线程有自己的堆栈和局部变量。
进程是系统程序执行和分配资源的基本单元。
线程是使用进程内存的空间,如QQ发消息是线程,是QQ给它的资源。
进程创建的时候会把主进程的东西都复制一遍,即是把代码都复制一遍来运行,但是并不是完全相同,入进程号等。代码在运行的过程中不会改变,改变的是数据。子进程会把主进程的内存,代码,资源等都复制一遍。总结:相当于代码是共享的。
手机里面的应用多开,就是多进程。进程先有才有线程。进程是资源分配的基本单位,线程是操作系统调度的基本单位。
真正运行的是线程。
进程与进程间是互相独立的。socket 通过网络可以进行进程间的通信,也可以通过文件完成进程间的通信(但是效率很低),和内存和磁盘的效率有关。
线程与进程的区别:必须有进程才能有线程,打个比方,进程就像车间里面的流水线,线程就是流水线上的工人。那个流水线就是资源,用这个资源的就是线程(工人)。一条流水线上面可以安排一个工人在那生产产品,但是效率很低,也浪费了流水线的资源。多线程的意思就是一条流水线上面安排了很多工人在那生产产品,生产产品的效率显然就会高很多,资源也得到了充分的利用。但是随着业务的发展,一条流水线虽然安排满了工人(即是进程里面开启了很多线程),还是无法满足市场的需求,因为一条流水线上的资源有限(工位有限),你分配再多的工人也提高不了多大的效率,多分配的人只能在那里闲着。所以想要提高效率,多生产产品,必须要多开几条流水线(即是多进程)。然后几条流水线一起生产产品,这样效率就会大大提高。所以说进程是资源的分配单位,线程是调度单位。即是真正干活的是线程(流水线工人),进程只是给线程提供资源(流水线工位)。必须有进程才有线程。线程不能独立运行,必须依存在进程中。即是工人不能独立地生成产品,必须依靠流水线才能完成一件产品的生产。一个QQ就是一个进程,它里面有很多线程,来执行操作系统调度。
#_author:'DJS'
#date:2018-12-07
import time
import threading
import random
from queue import Queue
def coding():
for i in range(3):
print("正在写代码%d"%i)
time.sleep(1)
def huatu():
for i in range(3):
print("正在画图%d"%i)
time.sleep(1)
def main():
t1 = threading.Thread(target=coding) #这里传的时候是传coding的并不是传conding()的
#传coding()指的是传一个函数的返回值(就是执行这个函数)
t2 = threading.Thread(target=huatu)
t1.start()
t2.start()
VALUE = 0 #定义一个全局变量
gLock = threading.Lock() #创建线程锁
def add_value():
global VALUE #在函数中引用或修改全局变量,要用global注明
gLock.acquire() #上锁
for i in range(1000000): #线程执行的次数多,量大的时候,
# 可能会造成线程不安全,造成数据 的错误。所以要对他进行上锁,然后解锁。
#锁只加在修改全局变量的地方,对于那些访问全局变量的地方不用添加。对个线程
#访问全局变量不会造成数据的错误
VALUE+=1
gLock.release() #解锁
print("最后执行完%d"%VALUE)
def main():
for x in range(10): #这里循环十次,表示的是add_value执行十次。
t = threading.Thread(target=add_value)
t.start()
##lock版的生成者与消费者模式
gMoney = 1000
gLock = threading.Lock() #创建一把锁
gTotaltime = 10
gTime = 0
class Producer(threading.Thread):
def run(self):
global gMoney
global gTime
while True:
monge = random.randint(100,1000) #随机产生100到1000的整数
gLock.acquire() #上锁
if gTime>=gTotaltime:
gLock.release() #在braek之前想要解锁。
break #在这里braek掉,但是加的锁还没有释放,程序会一直被锁死,运行不了其他的代码,braek的同时
#也要解锁
gMoney+=monge
print("%s生成了%d钱还剩%d钱"%(threading.current_thread(),monge,gMoney))
gTime+=1
gLock.release() #释放锁
time.sleep(0.5)
class Consumer(threading.Thread):
def run(self):
global gMoney
while True:
money = random.randint(100,1000)
gLock.acquire()
if gMoney >= money:
gMoney -= money
print("%s消费者消费了%d元钱,剩余%d元钱"%(threading.current_thread(),money,gMoney))
else:
if gTime>=gTotaltime:
gLock.release()
break #如果生成者不生产了,就释放锁,然后退出
print("%s消费者消费%d元钱,剩余%d,不足"%(threading.current_thread(),money,gMoney))
gLock.release()#解锁不能放在if里面,要对应起来放,要不然就成了死锁
time.sleep(0.5)
def main():
for i in range(5):
t = Producer(name="生成者线程%d"%i)
t.start()
for i in range(3):
t = Consumer(name="消费者线程%d"%i)
t.start()
##condition生产者与消费者模式
gMoney = 1000
gCondition = threading.Condition()#创建一把锁
gTotaltime = 10
gTime = 0
class Producer(threading.Thread):
def run(self):
global gMoney
global gTime
while True:
monge = random.randint(100,1000) #随机产生100到1000的整数
gCondition.acquire() #上锁
if gTime>=gTotaltime:
gCondition.release() #在braek之前想要解锁。
break #在这里braek掉,但是加的锁还没有释放,程序会一直被锁死,运行不了其他的代码,braek的同时
#也要解锁
gMoney+=monge
print("%s生成了%d钱还剩%d钱"%(threading.current_thread(),monge,gMoney))
gTime+=1
gCondition.notify_all() #生产完后就通知所有在等待的线程
gCondition.release() #释放锁
time.sleep(0.5)
class Consumer(threading.Thread):
def run(self):
global gMoney
while True:
money = random.randint(100,1000)
gCondition.acquire()
while gMoney < money:
if gTime>=gTotaltime:
gCondition.release()
return #退出这个函数的所有层循环
print("%s消费了%d元钱,还剩余%d元钱,不足"%(threading.current_thread(),money,gMoney))
gCondition.wait() #等待有钱的时候就释放锁
gMoney-=money
print("%s消费了%d元钱,剩余%d元钱"%(threading.current_thread(),money,gMoney))
gCondition.release()#解锁不能放在if里面,要对应起来放,要不然就成了死锁
time.sleep(0.5)
def main():
for i in range(5):
t = Producer(name="生成者线程%d"%i)
t.start()
for i in range(3):
t = Consumer(name="消费者线程%d"%i)
t.start()
##队列
q = Queue(4) #创建4个队列
q.put(1) #往队列中添加一个元素
print(q.qsize()) #q.qsize获取队列中总共有多少个元素
print(q.empty())#判断多了是否为空,是返回ture,不是空返回flase
print(q.full())#判断队列是否满了
for i in range(4): #往队列中添加4个数,这样队列就满了
q.put(i)
print(q.full())
for i in range(4):
print(q.get()) #从队列中拿数据出来,以先进先出的原则来拿
q.put(block=True) #,默认是阻塞式的,意思是往队列里面添加值
队列如果满了,就一直在那等,直到等到没有满
def set_value(q):
index = 0
while True:
q.put(index)
index+=1
time.sleep(1) #每隔一秒就往队列里面添加值
def get_value(q):
while True:
print(q.get()) #获取不到数据会一直在这里等,直到等到上面那个队列中添加有数据再打印
#即是一直处于阻塞状态
def main():
q = Queue(6)
t1 = threading.Thread(target=set_value,args=[q]) #创建一个线程,并这个方法里面往里面传递参数。
t2 = threading.Thread(target=get_value,args=[q]) #这个个类创建对象
t2 对于get_value 这个可以说是主线程,get_value 是子线程
Thread是threading这个包的一个类
t1.start() #主线程会等待子线程结束后再结束
t2.start()
if __name__ == '__main__':
main()
## 查看程序中的线程数
def test1():
for i in range(5):
print("test1%d"%i)
time.sleep(1)
def test2():
for i in range(5):
print("test2%d" % i)
time.sleep(1)
def main():
t1 = threading.Thread(target=test1) #target中指定一个线程名,那么这个线程就去函数里面执行了
t2 = threading.Thread(target=test2)
#target指定将来这个线程去那个函数执行代码
#args指定将来调用函数的时候传递什么数据过去,函数括号里面可以随便定义一个变量
#接收传递过去的数据,不是把args作为变量作为函数接收数据的参数
#多线程一般都是共享数据的,比如一个线程负责抓数据,一个线程负责处理数据,一个线程负责保存数据
#这样通过共享数据就可以完成了数据的爬取,处理,保存。
t1.start()
# time.sleep(1)
# t2.start()
# time.sleep(1)
# #time.sleep(1)#设置延时,让三个任务按照顺序来执行,查看线程数
# while True:
# print(threading.enumerate())
# if len(threading.enumerate())<=1:
# break
#一个线程的开始是在star()那里开始的
# #这是三个任务,执行的先后顺序是操作系统说了算
#操作系统可能先执行t1,也可以先执行t2,三个任务的执行顺序是无序的
#线程的运行是无序的,随机的。所以想要三个任务按照顺序来执行就要设置
#延时了,分别在其他两个那里设置延时就可以按照顺序执行了
if __name__ == '__main__':
main()