• 线程、进程和协程


    1、python 线程

    Threading 用于提供线程相关的操作,线程是应用程序中工作最小的单元。

     1 #-*-coding:utf-8-*-
     2 #!/usr/bin/env python
     3 __author__ = 'bravexz'
     4 
     5 import threading
     6 import time
     7 
     8 def show(arg):
     9     time.sleep(1)
    10     print "thread"+str(arg)
    11 
    12 for i in range(10):
    13     t = threading.Thread(target=show,args=(i,))
    14     t.start()
    15 
    16 print "main thread stop"

    上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行命令。

    • start            线程准备就绪,等待CPU调度
    • setName      为线程设置名称
    • getName      获取线程名称
    • setDaemon   设置为后台线程或前台线程(默认)
                         如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止
                          如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完成后,程序停止
    • join              逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
    • run              线程被cpu调度后执行Thread类对象的run方法

    2、线程锁

    由于线程之间是进行随机调度,并且每个线程可能只执行n条指令之后,CPU接着执行其他线程,所以可能出现如下问题:

     1 import time
     2 import threading
     3 
     4 g1_num = 0
     5 def show(arg):
     6     global g1_num
     7     time.sleep(1)
     8     g1_num +=1
     9     print g1_num
    10 
    11 for i in range(10):
    12     t = threading.Thread(target=show,args=(i,))
    13     t.start()
    14 print "main thread stop"

    为了解决上面的问题,我们加入了线程锁机制,能够很好的解决以上问题了。

     1 import threading
     2 import time
     3 
     4 g1_num = 0
     5 lock = threading.RLock()
     6 def Func():
     7     lock.acquire()
     8     global g1_num
     9     g1_num +=1
    10     time.sleep(1)
    11     print g1_num
    12     lock.release()
    13 
    14 for i in range(10):
    15     t = threading.Thread(target=Func)
    16     t.start()

    3、event

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

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

    • clear:将“Flag”设置为False
    • set:将“Flag”设置为True
     1 import threading
     2 
     3 def do(event):
     4     print "start"
     5     event.wait()
     6     print "execute"
     7 
     8 event_obj = threading.Event()
     9 for i in range(10):
    10     t = threading.Thread(target=do,args=(event_obj,))
    11     t.start()
    12 
    13 event_obj.clear()
    14 inp = raw_input("input:")
    15 if inp == "true":
    16     event_obj.set()

    4、python 进程

     1 from multiprocessing import Process
     2 import threading
     3 import time
     4 
     5 def foo(i):
     6     print "say hi",i
     7 
     8 for i in range(10):
     9     p = Process(target=foo,args=(i,))
    10     p.start()

    输入结果:

    say hi 0
    say hi 1
    say hi 4
    say hi 3
    say hi 5
    say hi 7
    say hi 9
    say hi 2
    say hi 8
    say hi 6

    注明:以上代码必须在linux才可以正常运行。

    4.1 进程数据共享

    进程各自持有一份数据,默认无法共享数据

     1 from multiprocessing import Process
     2 from multiprocessing import Manager
     3 import time
     4 
     5 li = []
     6 def foo(i):
     7     li.append(i)
     8     print "say,hi",li
     9 
    10 if __name__ == "__main__":
    11     for i in range(10):
    12         p = Process(target=foo,args=(i,))
    13         p.start()
    14 print "ending",li

    输出结果:

    ending []
    ending []
    say,hi [3]
    ending []
    say,hi [6]
    ending []
    say,hi [2]
    ending []
    say,hi [7]
    ending []
    say,hi [0]
    ending []
    say,hi [4]
    ending []
    say,hi [8]
    ending []
    say,hi [1]
    ending []
    say,hi [9]
    ending []
    say,hi [5]

    如果解决这个问题呢,看下图:

     1 from multiprocessing import Process,Array
     2 temp = Array("i",[11,22,33,44])
     3 
     4 def Foo(i):
     5     temp[i] = 100+i
     6     for item in temp:
     7         print i,"------>",item
     8 
     9 if __name__ == "__main__":
    10     for i in range(2):
    11         p = Process(target=Foo,args=(i,))
    12         p.start()

    输出结果:

    0 ------> 100
    0 ------> 22
    0 ------> 33
    0 ------> 44
    1 ------> 11
    1 ------> 101
    1 ------> 33
    1 ------> 44

     1 from multiprocessing import Process,Manager
     2 manage = Manager()
     3 dic = manage.dict()
     4 def Foo(i):
     5     dic[i] = 100+i
     6     print dic.values()
     7 for i in range(2):
     8     p = Process(target=Foo,args=(i,))
     9     p.start()
    10     p.join()

    输出结果:

    [root@centos6 lab]# python oldboy10.1.py
    [100]
    [100, 101]

    当创建进程时(非使用时),共享数据会被拿到子进程中,当进程执行完毕后,再赋值给原值。

    一下为进程锁实例:

     1 from multiprocessing import Process, Array, RLock
     2 
     3 def Foo(lock,temp,i):
     4     lock.acquire()
     5     temp[0] = 100+i
     6     for item in temp:
     7         print i,'----->',item
     8     lock.release()
     9 
    10 lock = RLock()
    11 temp = Array('i', [11, 22, 33, 44])
    12 
    13 for i in range(5):
    14     p = Process(target=Foo,args=(lock,temp,i,))
    15     p.start()
    执行、运行结果:

    [root@centos6 lab]# python oldboy10.2.py
    0 -----> 100
    0 -----> 22
    0 -----> 33
    0 -----> 44
    2 -----> 102
    2 -----> 22
    2 -----> 33
    2 -----> 44
    3 -----> 103
    3 -----> 22
    3 -----> 33
    3 -----> 44
    4 -----> 104
    4 -----> 22
    4 -----> 33
    4 -----> 44
    1 -----> 101
    1 -----> 22
    1 -----> 33
    1 -----> 44
    [root@centos6 lab]#

    4.2、进程池

    进程池内部维护一个进程序列,当使用时,去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

    进程池中有两个方法:

    • apply
    • apply_async
     1 from multiprocessing import Process,Pool
     2 import time
     3 
     4 def Foo(i):
     5     time.sleep(2)
     6     return i+100
     7 def Bar(arg):
     8     print arg
     9 pool = Pool(5)
    10 
    11 for i in range(10):
    12     pool.apply_async(func=Foo,args=(i,),callback= Bar)
    13 print "end"
    14 pool.close()
    15 pool.join()
    输出结果如下:

    [root@centos6 lab]# python oldboy10.3.py
    end
    100
    102
    104
    103
    101
    106
    109
    108
    107
    105
    [root@centos6 lab]#

     5、协程

    线程与进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。

    协程存在的意义:用于多线程的应用,CPU通过切片的方式来切换线程间的执行,而线程切换时需要耗时(保存状态,下次继续)。协程则只使用一个线程,在一个线程中规定某个代码块执行顺序。

    协程的适用场景:当程序中存在大量不需要CPU的操作时(I/O),适用于协程。

  • 相关阅读:
    SpringBoot启动项目时提示:Error:java: 读取***.jar时出错;
    K8S操作
    二、kubernetes搭建集群
    三、Json方式函数
    一、Gulp
    大萨达所
    三、IIS通过目录方式部署以供外部调试
    四、附加到进程调试(.NET Framework)
    一、bootstrap-fontawesome-iconpicker组件
    表单
  • 原文地址:https://www.cnblogs.com/bravexz/p/5115651.html
Copyright © 2020-2023  润新知