进程和线程

进程:进程是程序的一次执行,每个进程都有自己的地址空间、内存、数据栈,以及其他记录其运行轨迹的辅助数据。操作系统管理在其上面运行的所有进程,并为这些进程公平的分配时间。

线程:(轻量型进程)所有的线程都运行在同一个进程中,共享相同的运行环境。

单线程和多线程

单线程:

单线程中处理器要处理多个任务时,必须对这些任务安排优先级,先执行谁后执行谁。

onethread.py

from time import *
def movie(name,loop):            #线程1
    for i in range(loop):
        print("我在电影:%s,现在是:%s"%(name,ctime()))
        sleep(2)
def music(name,loop):            #线程2
    for i in range(loop):
        print("我在听音乐:%s,现在是:%s"%(name,ctime()))
        sleep(2)
if __name__ == "__main__":
    movie("爱我别跑",2)
    music("流星雨",3)

多线程:

Python通过thread库和threading库提供对线程的支持。thread库和threading库的区别:

  • thread库提供了低级别的、原始的线程以及一个简单的锁;
  • threading库是基于Java的线程模式设计,锁lock和条件变量condition在Java中是对象的基本行为(每一个对象都自带了锁和条件变量),而在Python中则是独立的对象;
  • thread库不支持守护线程,也就是当主线程退出时,所有的子线程都会强行退出,不管其工不工作;
  • threading库支持守护线程,主线程退出后仍在工作的子线程不会退出。

所以请使用threading库。


threads1.py

from time import *
import threading
#线程1
def music(name,loop):
    for i in range(loop):
        print("我在听:%s,现在是%s"%(name,ctime()))
        sleep(2)
#线程2
def movie(name,loop):
    for i in range(loop):
        print("我在看:%s,现在是%s"%(name,ctime()))
        sleep(2)

#创建空数组用来装载线程1,2
threads =[]

#创建线程t1,并添加到线程组threads
t1 = threading.Thread(target=music,args=("后来",2))
threads.append(t1)

#创建线程t2,并添加到线程组threads
t2 = threading.Thread(target=movie,args=("超人3",2))
threads.append(t2)

if __name__ == "__main__":
    #启动线程
    for i in threads:
        i.start()  #开始线程活动
    #守护线程
    for i in threads:
        i.join()   #等待线程终止
    print("运行结束了。")

python 进程创建线程 python的线程和进程_多进程

可以看到两个线程并行工作!!!!!

threading.Thread(target=,args=(),name=None,group=None,kwargs={})

  • target表示调用的对象;
  • args表示调用对象的位置参数元组;
  • kwargs表示调用对象的字典;
  • name表示该线程名;
  • group实际上不使用。

上面的例子中可发现线程的创建有些麻烦,每创建一个线程需要创建一个t(t1,t2,t3...)当创建的线程很多的时候这样极其不方便,

下面是优化的多线程:

threads2.py

from time import sleep,ctime
import threading

def super_player(file_,time):
    for i in range(2):
        print('开始播放:%s!%s'%(file_,ctime()))
        sleep(time)

#播放文件和播放时长
dicts ={'真爱.mp3':2,'阿凡达.mp4':5,'我和你':4}

#创建线程空数组,用于存放线程
threads =[]
files = range(len(dicts))

#创建线程(遍历字典)并添加到线程数组内
for file_,time in dicts.items():
    t = threading.Thread (target=super_player,args=(file_,time))
    threads.append(t) #

if __name__ =='__main__':
    #启动线程
    for i in files:
        threads[i].start()
    #守护线程
    for i in files:
        threads[i].join()

    print('end all:%s'%ctime())

自定义线程类

除了使用python提供的线程外,我们可以根据自己的需求定义自己的线程类:

mythreads.py

import threading
from time import sleep,ctime

#创建线程类
class MyThread(threading.Thread):

    def __init__(self,func,args,name=''):
        threading.Thread.__init__(self)   #super().__init__()
        self.func = func
        self.args = args
        self.name = name

    def run(self):
        self.func(*self.args)  #python2不支持这种方式

def super_play(file_,time):
    for i in range(2):
        print("开始播放:%s!%s"%(file_,ctime()))
        sleep(time)

dicts ={"真爱.mp3":3,"阿凡达.mp4":5,"我和你.mp3":5}

threads =[]
files = range(len(dicts))

for file_,time in dicts.items():
    t = MyThread(super_play,(file_,time),super_play.__name__)
    threads.append(t)

if __name__=='__main__':
    #启动线程
    for i in files:
        threads[i].start()
    for i in files:
        threads[i].join()
    print('all end:%s'%ctime())

多进程技术

多进程使用multiprocessing模块,与多线程的threading模块用法类似。

多进程的优势:

multiprocessing提供了本地和远程的并发性,有效地通过全局解释锁(GIL)来使用进程而不是线程。由于GIL的存在,在CPU密集型的程序当中,使用多线程并不能有效地利用多核CPU的优势,因为一个解析器在同一时刻只会有一个线程在执行。所以muitiprocessing模块可以充分利用硬件的多处理器来进行工作。

多进程使用的multiprocessing模块使用Process对象来创建一个进程,Process对象使用和多线程的Thread对象使用方法相同,

  • start() 开启进程活动;
  • run()   运行进程
  • join() 等待进程的终止

multiprocessing.Process(target=,args=(),name=,kwargs={},group=None)


  • target表示调用的对象;
  • args表示调用对象的位置参数,元组;
  • kwargs表示调用对象的字典,字典{};
  • name进程的名字;
  • group实际上不使用。


process.py

from time import *
import multiprocessing

def surper_player(file_,time):
    for i in range(2):
        print('start playing:%s.%s'%(file_,ctime()))
        sleep(time)
lists ={'loving.mp3':3,'makeloving.mp4':5}
threads =[]
files =range(len(lists))
#创建进程
for file_,time in lists.items():
    t =multiprocessing.Process(target=surper_player,args=(file_,time))
    threads.append(t)
if __name__ =="__main__":
    #启动进程
    for t in files:
        threads[t].start()

    for t in files:
        threads[t].join()


python 进程创建线程 python的线程和进程_创建线程_02


运行结果和多线程几乎一样。。。

Pipe和Queue

IPC进程间通信

pipe.py

import multiprocessing
from time import ctime

def proc1(pipe):
    pipe.send('hello')                       #进程从pipe一端输入对象
    print('proc1 rec:',pipe.recv(),ctime()) #被pipe另一端的进程接收
def proc2(pipe):
    print('proc2 rec:',pipe.recv(),ctime()) #被pipe一段的进程接收
    pipe.send('hello,too.')                  #进程从pipe另一端输入对象
#这里的pipe双向的,pipe对象建立的时候,返回一个含有两个元素的表,每个元素代表pipe的一端,对pipe的某一端调用send()方法来传送对象,在另一端使用recv()接收
if __name__ =="__main__":
    multiprocessing.freeze_support()
    pipe = multiprocessing.Pipe()

    p1 = multiprocessing.Process(target=proc1,args=(pipe[0],))
    p2 = multiprocessing.Process(target=proc2,args=(pipe[1],))

    p1.start()
    p2.start()
    p1.join()
    p2.join()

queque.py

import multiprocessing,os
from time import *
def inputQ(queue):
    info = str(os.getpid()) + 'put():' + str(ctime())
    queue.put(info)

def outputQ(queue,lock):
    info = queue.get()
    lock.acquire()
    print((str(os.getpid()) + 'get():' + info))
    lock.release()

if __name__ =="__main__":
    record1 = []
    record2 = []
    lock = multiprocessing.Lock()
    queue = multiprocessing.Queue(3)
    for i in range(10):
        process = multiprocessing.Process(target=inputQ,args=(queue,))
        process.start()
        record1.append(process)
        
    for i in range(10):
        process =multiprocessing.Process(target=outputQ,args=(queue,lock))
        process.start()
        record2.append(process)

    for i in record1 :
        i.join()
    queue.close()
    for i in record2:
        i.join()