python多进程,多线程,协程

版权声明: https://blog.csdn.net/djs123DJS/article/details/84451616

线程依赖于进程,协程依赖于线程,效率最好的是协程,其次到线程,再到进程。总结:单线程会阻塞,协程不会阻塞。主要看会不会阻塞,其次看耗不耗资源。对比之下协程是最好的。

主线程结束,子线程才会结束。程序和进程通俗来讲就是一个运行一个不运行,不运行的叫程序,运行起来的叫进程。程序只有一个,但是进程可以有多个,即是一个程序可以对应多个进程。进程是一个拥有资源的地方。资源是一个资源分配的地方。如一个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()

猜你喜欢

转载自blog.csdn.net/djs123DJS/article/details/84451616