线程,进程概念

当多个客户端访问服务端的时候,每个客户端都会对服务端说:’嗨,我想连接你‘。服务端的sorcket通过while循环,一直监听着是否有client请求连接,当有请求(一个或者多个)连接过来的时候:就会分配(一个或者多个)进程或者线程给client,并保持连接,进行通话。

线程是应用程序的最小单位,

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
  
def show(arg):
    time.sleep(2)
    print 'thread'+str(arg)
  
for i in range(10):
    t = threading.Thread(target=show, args=(i,))  #这里实例化对象的时候传的两个参数第一个参数是,线程需要执行的方法,第二个参数方法的参数
    t.start()
  
print 'main thread stop'
View Code

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

再次回顾:这里为什么是分片执行?

python中的多线程,有一个GIL(Global Interpreter Lock 全局解释器锁 )在同一时间只有一个线程在工作,他底层会自动进行上下文切换.这个线程执行点,那个线程执行点!

更多方法:请自己多查看源码,多看,多看,看不懂,再看。

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

线程锁:

无线程锁:(多个线程同时对一个内存地址进行操作)
#!/sur/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'ganzl'
import threading
import time
gl_num = 0
def show(arg):
    global gl_num
    time.sleep(1)
    gl_num +=1
    print gl_num

for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()
print 'main thread stop'
View Code
有线程锁:
#!/sur/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'ganzl'
import threading
import time
gl_num = 0
lock = threading.RLock() #实例化调用线程锁
def Func():
    lock.acquire() #获取线程锁
    global gl_num
    gl_num +=1
    time.sleep(1)
    print gl_num
    lock.release() #释放线程锁,这里注意,在使用线程锁的时候不能把锁,写在代码中,否则会造成阻塞,看起来“像”单线程

for i in range(10):
    t = threading.Thread(target=Func)
    t.start()
View Code

event

python线程的事件用于主线程控制其他子线程的控制。

事件主要提供了三个方法 set、wait、clear。

事件处理的机制:

  全局定义了一个“Flag”,如果“Flag”值为 False,那么当程序执行 event.wait 方法时就会阻塞,

              如果“Flag”值为True,那么event.wait 方法时便不再阻塞。

  • clear:将“Flag”设置为False
  • set:将“Flag”设置为True
#!/sur/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'ganzl'
import threading
def do(event):
    print 'start'
    event.wait() #执行对象weit方法,然后他们停下来,等待“Flag”为True
    print 'execute'
event_obj = threading.Event() #创建事件的对象
for i in range(2):
    t = threading.Thread(target=do, args=(event_obj,)) #执行多线程。
    t.start()
print dir(event_obj)
print event_obj.__dict__
print event_obj.__dict__['_Event__flag']

inp = raw_input('input:')
if inp == 'true':
    event_obj.set()
    print event_obj.__dict__['_Event__flag']

多进程:

注意:由于进程之间的数据需要各自持有一份,所以创建进程需要的非常大的开销。

并且python不能再Windows下创建进程!(pycharm不能执行多线程的demo)

并且在使用多进程的时候,最好是创建多少个进程?:和CPU核数相等

Linux下,工作中用到的批量执行命令的demo:

#!/sur/bin/env python
# -*- coding:utf-8 -*-
__author__ = 'ganzl'
import multiprocessing
import sys,os,time
import paramiko

def ssh_cmd(host,port,user,passwd,cmd):
    msg = "-----------Result:%s----------" % host
    s = paramiko.SSHClient()
    s.load_system_host_keys()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    try:
        s.connect(host,22,user,passwd,timeout=5)
        stdin,stdout,stderr = s.exec_command(cmd)

        cmd_result = stdout.read(),stderr.read()
        print msg
        for line in cmd_result:
                print line,

        s.close()
    except paramiko.AuthenticationException:
        print msg
        print 'AuthenticationException Failed'
    except paramiko.BadHostKeyException:
        print msg
        print "Bad host key"

p = multiprocessing.Pool(processes=20)
#----------------等他与上面那一句
#from multiprocessing import Process,Pool
#p = Pool(20)
#----------------
cmd=raw_input('CMD:')
f=open('serverlist.conf')#当前目录下建立该配置文件,格式按照如下的方式
list = f.readlines()
f.close()
for IP in list:
    host=IP.split()[0]
    port=int(IP.split()[1])
    user=IP.split()[2]
    passwd=IP.split()[3]
    p.apply_async(ssh_cmd,(host,port,user,passwd,cmd))#多进程执行的一个方法。

p.close()
p.join()

进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,

如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。

进程池中有两个方法及demo:

  • apply
  • apply_async
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from  multiprocessing import Process,Pool
import time
  
def Foo(i):
    time.sleep(2)
    return i+100
  
def Bar(arg):
    print arg
  
pool = Pool(5)
#print pool.apply(Foo,(1,))
#print pool.apply_async(func =Foo, args=(1,)).get()
  
for i in range(10):
    pool.apply_async(func=Foo, args=(i,),callback=Bar)
  
print 'end'
pool.close()
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
View Code

多进程之间,也可以数据共享,同时数据共享时,产生脏数据时,也可以用锁进行锁定,防止脏数据。

这个平时没用到过,有碰到时,再度娘吧。

协程:(这个平时也没用到过,先标注下概念,以后有用到再加深吧)

线程和进程都是系统帮咱们开辟的。
对于协程来说,是程序员操控的。

协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。

        协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。

适用场景:其实在其他语言中,协程的其实是意义不大的多线程即可已解决I/O的问题,但是在python因为他有GIL(Global Interpreter Lock 全局解释器锁 )在同一时间只有一个线程在工作,所以:如果一个线程里面I/O操作特别多,协程就比较适用

demo的话,自己整特明白了再说。

关于更多请参考:http://www.cnblogs.com/wupeiqi/articles/4839959.html(写的很不错)

原文地址:https://www.cnblogs.com/shoug/p/5137360.html