线程、进程、携程

进程: qq 要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,内存的管理,网络接口的调用等。。。对各种资源管理的集合 就可以成为 进程

线程: 是操作系统最小的调度单位, 是一串指令的集合(在python中同一时间执行的线程只有一个)python多线程 不适合cpu密集操作型的任务,适合io操作密集型的任务

进程 要操作cpu , 必须要先创建一个线程 ,所有在同一个进程里的线程是共享同一块内存空间的

进程与线程的区别?
1.线程共享内存空间,进程的内存是独立的

2.同一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现

3.创建新线程很简单, 创建新进程需要对其父进程进行一次克隆

4.一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程

启动线程:(主线程不等子线程)程序在退出之前默认等待所有线程执行完毕

import threading
import time

def run(n):
    print("task ",n )
    time.sleep(2)
    print("task done",n)

start_time = time.time()
for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.start()

print("----------all threads has finished...")
print("cost:",time.time() - start_time)

启动线程:(主线程等待子线程执行完毕)

import threading
import time

def run(n):
    print("task ",n )
    time.sleep(2)
    print("task done",n)

start_time = time.time()
t_objs = [] #存线程实例
for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.start()
    t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里

for t in t_objs: #循环线程实例列表,等待所有线程执行完毕
    t.join()

print("----------all threads has finished...")
print("cost:",time.time() - start_time)

守护进程(即守护线程):以上主线程等待子线程执行完毕的过程中,虽然主线程没有等待子线程,但是在程序结束的时候默认等待所有的子线程结束。而守护进程在程序结束的时候是不需要等待守护进程执行结束的

import threading
import time

def run(n):
    print("task ",n )
    time.sleep(2)
    print("task done",n,threading.current_thread())

start_time = time.time()
for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.setDaemon(True) #把当前线程设置为守护线程
    t.start()

#print("----------all threads has finished...",threading.current_thread(),threading.active_count())
print("cost:",time.time() - start_time)

线程锁(也叫互斥锁)的应用:(防止多个线程对同一份资源的处理发生冲突, 上完锁之后程序变成了串行)python3程序自己上锁了

import threading
import time

def run(n):
    lock.acquire()
    global  num
    num +=1
    time.sleep(1)
    lock.release()

lock = threading.Lock()
num = 0
t_objs = [] #存线程实例
for i in range(50):
    t = threading.Thread(target=run,args=("t-%s" %i ,))
    t.start()
    t_objs.append(t) #为了不阻塞后面线程的启动,不在这里join,先放到一个列表里

for t in t_objs: #循环线程实例列表,等待所有线程执行完毕
    t.join()print("num:",num)

递归锁的应用:(如果出现锁中有锁就需要递归锁,如果不用递归锁而把锁的顺序混淆就会出现卡死现象)

import threading

def run1():
    print("grab the first part data")
    lock.acquire()
    global num
    num += 1
    lock.release()
    return num

def run2():
    print("grab the second part data")
    lock.acquire()
    global num2
    num2 += 1
    lock.release()
    return num2

def run3():
    lock.acquire()
    res = run1()
    print(‘--------between run1 and run2-----‘)
    res2 = run2()
    lock.release()
    print(res, res2)

num, num2 = 0, 0
lock = threading.RLock()
for i in range(1):
    t = threading.Thread(target=run3)
    t.start()

while threading.active_count() != 1:
    print(threading.active_count())
else:
    print(‘----all threads done---‘)
    print(num, num2)

信号量:(互斥锁 同时只允许一个线程更改数据,而Semaphore是同时允许一定数量的线程更改数据)

import threading, time

def run(n):
    semaphore.acquire()
    time.sleep(1)
    print("run the thread: %s\n" % n)
    semaphore.release()

if __name__ == ‘__main__‘:
    semaphore = threading.BoundedSemaphore(5)  # 最多允许5个线程同时运行
    for i in range(22):
        t = threading.Thread(target=run, args=(i,))
        t.start()
while threading.active_count() != 1:
    pass  # print threading.active_count()
else:
    print(‘----all threads done---‘)

Event:(来实现两个或多个线程间的交互)

import time
import threading

event = threading.Event()

def lighter():
    count = 0
    event.set() #先设置绿灯
    while True:
        if count >5 and count < 10: #改成红灯
            event.clear() #把标志位清了
            print("\033[41;1mred light is on....\033[0m")
        elif count >10:
            event.set() #变绿灯
            count = 0
        else:
            print("\033[42;1mgreen light is on....\033[0m")
        time.sleep(1)
        count +=1

def car(name):
    while True:
        if event.is_set(): #代表绿灯
            print("[%s] running..."% name )
            time.sleep(1)
        else:
            print("[%s] sees red light , waiting...." %name)
            event.wait()
            print("\033[34;1m[%s] green light is on, start going...\033[0m" %name)

light = threading.Thread(target=lighter,)
light.start()

car1 = threading.Thread(target=car,args=("Tesla",))
car1.start()

queue队列:(作用是解耦和提高效率)

import threading,time
import queue

q = queue.Queue(maxsize=10)

def Producer(name):
    count = 1
    while True:
        q.put("骨头%s" % count)
        print("生产了骨头",count)
        count +=1
        time.sleep(0.1)

def  Consumer(name):
    #while q.qsize()>0:
    while True:
        print("[%s] 取到[%s] 并且吃了它..." %(name, q.get()))
        time.sleep(1)

p = threading.Thread(target=Producer,args=("Alex",))
c = threading.Thread(target=Consumer,args=("ChengRonghua",))
c1 = threading.Thread(target=Consumer,args=("王森",))

p.start()
c.start()
c1.start()

多进程:用法上和多线程一样。每个子进程都是由父进程启动的。

import multiprocessing
import time

def run(name):
    time.sleep(2)
    print("hello", name)

if __name__ == "__main__":
    p = multiprocessing.Process(target=run, args=(‘bob‘, ))
    p.start()
    p.join()

父进程启动子进程:

from multiprocessing import Process
import os

def info(title):
    print(title)
    print(‘module name:‘, __name__)
    print(‘parent process:‘, os.getppid())
    print(‘process id:‘, os.getpid())
    print("\n\n")

def f(name):
    info(‘\033[31;1mcalled from child process function f\033[0m‘)
    print(‘hello‘, name)

if __name__ == ‘__main__‘:
    info(‘\033[32;1mmain process line\033[0m‘)
    p = Process(target=f, args=(‘bob‘,))
    p.start()
    p.join()

进程间通讯(Queue):(以下这个例子中父进程的队列取到了子进程中队列的数,这其实是子进程从父进程中克隆了一份队列,然后这两个进程中的队列通过pickle进行互通)这只是实现了数据的传输

from multiprocessing import Process, Queue

def f(qq):
    qq.put([42, None, ‘hello‘])

if __name__ == ‘__main__‘:
    q = Queue()
    p = Process(target=f, args=(q,))
    p.start()
    print(q.get())

进程间通讯(Pipe):实现了数据的传递。

from multiprocessing import Process, Pipe

def f(conn):
    conn.send([42, None, ‘hello from child‘])
    conn.send([42, None, ‘hello from child2‘])
    print("from parent:",conn.recv())
    conn.close()

if __name__ == ‘__main__‘:
    parent_conn, child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    print(parent_conn.recv())  # prints "[42, None, ‘hello‘]"
    print(parent_conn.recv())  # prints "[42, None, ‘hello‘]"
    parent_conn.send("张洋可好") # prints "[42, None, ‘hello‘]"
    p.join()

进程间通讯(Manager):实现了进程间数据的共享和传输。

from multiprocessing import Process, Manager
import os
def f(d, l):
    d[os.getpid()] =os.getpid()
    l.append(os.getpid())
    print(l)

if __name__ == ‘__main__‘:
    with Manager() as manager:
        d = manager.dict() #生成一个字典,可在多个进程间共享和传递

        l = manager.list(range(5))#生成一个列表,可在多个进程间共享和传递
        p_list = []
        for i in range(10):
            p = Process(target=f, args=(d, l))
            p.start()
            p_list.append(p)
        for res in p_list: #等待结果
            res.join()

        print(d)
        print(l)

进程锁:虽然进程间的数据是相互独立的,但是他们在打印的时候需要占用同一块屏幕,所以需要锁来保证打印不会混乱。

from multiprocessing import Process, Lock

def f(l, i):
    l.acquire()
    print(‘hello world‘, i)
    l.release()

if __name__ == ‘__main__‘:
    lock = Lock()
    for num in range(100):
        Process(target=f, args=(lock, num)).start()

进程池:同一时间由多少进程在运行。以下的回调函数是主进程调用的

from  multiprocessing import Process, Pool
import time
import os

def Foo(i):
    time.sleep(2)
    print("in process",os.getpid())
    return i + 100

def Bar(arg):
    print(‘-->exec done:‘, arg,os.getpid())

if __name__ == ‘__main__‘:
    pool = Pool(processes=3) #允许进程池同时放入5个进程
    print("主进程",os.getpid())
    for i in range(10):
        pool.apply_async(func=Foo, args=(i,), callback=Bar) #callback=回调
        #pool.apply(func=Foo, args=(i,)) #串行
        #pool.apply_async(func=Foo, args=(i,)) #并行
    print(‘end‘)
    pool.close()
    pool.join() #进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。.join()

协程:协程是一种用户态的轻量级线程。(cpu都不知道它的存在)就是在单线程中,适合高并发处理。但不能用于多核

yield实现简单的携程:

import timedef consumer(name):
    print("--->starting eating baozi...")
    while True:
        new_baozi = yield
        print("[%s] is eating baozi %s" % (name, new_baozi))

def producer():
    r = con.__next__()
    r = con2.__next__()
    n = 0
    while n < 5:
        n += 1
        con.send(n)
        con2.send(n)
        time.sleep(1)
        print("\033[32;1m[producer]\033[0m is making baozi %s" % n)

if __name__ == ‘__main__‘:
    con = consumer("c1")
    con2 = consumer("c2")
    p = producer()

greenlet携程:对携程进行了封装,需要手动进行切换

from greenlet import greenlet
def test1():
    print(12)
    gr2.switch()
    print(34)
    gr2.switch()
def test2():
    print(56)
    gr1.switch()
    print(78)

gr1 = greenlet(test1) #启动一个携程
gr2 = greenlet(test2)
gr1.switch()

Gevent:自动进行切换

import gevent

def foo():
    print(‘Running in foo‘)
    gevent.sleep(2)
    print(‘Explicit context switch to foo again‘)
def bar():
    print(‘Explicit精确的 context内容 to bar‘)
    gevent.sleep(1)
    print(‘Implicit context switch back to bar‘)
def func3():
    print("running func3 ")
    gevent.sleep(0)
    print("running func3  again ")

gevent.joinall([
    gevent.spawn(foo), #生成一个携程
    gevent.spawn(bar),
    gevent.spawn(func3),
])

用携程爬取内容:

from urllib import request
import gevent,time
from gevent import monkey
monkey.patch_all() #把当前程序的所有的io操作给我单独的做上标记

def f(url):
    print(‘GET: %s‘ % url)
    resp = request.urlopen(url)
    data = resp.read()
    print(‘%d bytes received from %s.‘ % (len(data), url))

urls = [‘https://www.python.org/‘,
        ‘https://www.yahoo.com/‘,
        ‘https://github.com/‘ ]
time_start = time.time()
for url in urls:
    f(url)
print("同步cost",time.time() - time_start)
async_time_start = time.time()
gevent.joinall([
    gevent.spawn(f, ‘https://www.python.org/‘),
    gevent.spawn(f, ‘https://www.yahoo.com/‘),
    gevent.spawn(f, ‘https://github.com/‘),
])
print("异步cost",time.time() - async_time_start)

用携程实现socket:

服务器端:

import sys
import socket
import time
import gevent

from gevent import socket, monkey

monkey.patch_all()

def server(port):
    s = socket.socket()
    s.bind((‘0.0.0.0‘, port))
    s.listen(500)
    while True:
        cli, addr = s.accept()
        gevent.spawn(handle_request, cli)

def handle_request(conn):
    try:
        while True:
            data = conn.recv(1024)
            print("recv:", data)
            conn.send(data)
            if not data:
                conn.shutdown(socket.SHUT_WR)

    except Exception as  ex:
        print(ex)
    finally:
        conn.close()

if __name__ == ‘__main__‘:
    server(8001)

客户端:

import socket

HOST = ‘localhost‘  # The remote host
PORT = 9999  # The same port as used by the server
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
while True:
    msg = bytes(input(">>:"), encoding="utf8")
    s.sendall(msg)
    data = s.recv(1024)    print(‘Received‘, data)
s.close()

事件驱动模型
事件驱动模型大体思路如下:
1. 有一个事件(消息)队列;
2. 鼠标按下时,往这个队列中增加一个点击事件(消息);
3. 有个循环,不断从队列取出事件,根据不同的事件,调用不同的函数,如onClick()、onKeyDown()等;
4. 事件(消息)一般都各自保存各自的处理函数指针,这样,每个消息都有独立的处理函数;

原文地址:https://www.cnblogs.com/czz0508/p/11066593.html

时间: 2024-10-09 11:50:08

线程、进程、携程的相关文章

线程 进程 协程

一.什么是线程? 线程是操作系统能够进行运算调度的最小单位(程序执行流的最小单元).它被包含在进程之中,是进程中的实际运作单位.一条线程指的是一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成.另外,线程是进程的中的一个实体,是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程的其它线程共享进程所拥有的全部资源.一个线程可以创建和撤销另一

15.python并发编程(线程--进程--协程)

一.进程:1.定义:进程最小的资源单位,本质就是一个程序在一个数据集上的一次动态执行(运行)的过程2.组成:进程一般由程序,数据集,进程控制三部分组成:(1)程序:用来描述进程要完成哪些功能以及如何完成(2)数据集:是程序在执行过程中所需要使用的一切资源(3)进程控制块:用来记录进程外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志.3.进程的作用:是想完成多任务并发,进程之间的内存地址是相互独立的二.线程:1.定义:最小的执行单位,线程的出现是为了

11 线程进程协程

1 线程 1.1 基本应用 1.1.1 标准线程(常用) import threading def f1(arg): print(arg) t = threading.Thread(target=f1, args=(123,)) t.start() 1.1.2 自定义线程 自定义线程类既threading.Thread流程,自定义run方法 import threading class MyThread(threading.Thread): #自定义类,继承threading.Thread类 d

Python的线程&amp;进程&amp;协程[0] -&gt; 基本概念

基本概念 / Basic Concept 0 简介与动机 / Why Multi-Thread/Multi-Process/Coroutine 在多线程(multithreaded, MT)编程出现之前,计算机程序的执行是由单个步骤序列组成的,该序列在主机的CPU中按照同步顺序执行.即无论任务多少,是否包含子任务,都要按照顺序方式进行. 然而,假定子任务之间相互独立,没有因果关系,若能使这些独立的任务同时运行,则这种并行处理方式可以显著提高整个任务的性能,这便是多线程编程. 而对于Python而

第九天 线程 进程 协程 队列

详细链接http://www.cnblogs.com/alex3714/articles/5230609.html 1.线程:包含在进程中,是操作系统运算调度的最小单位,是一串指令的集合,直接与cpu交互 2进程:进程是一个程序各种资源的集合.操作系统通过管理这个集合进而运行程序,进程本身并不执行,进程通过调用线程来调度cpu. 3.不同点: 一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程 创建新线程很简单,但是创建一个子进程需要对父进程进行拷贝 线程共享内存,进程的内存是独

Python的线程&amp;进程&amp;协程[0] -&gt; 线程 -&gt; 多线程的建立与使用

常用的多线程功能实现 目录 生成线程的三种方法 单线程与多线程对比 守护线程的设置 1 生成线程的三种方法 三种方式分别为: 创建一个Thread实例,传给它一个函数 创建一个Thread实例,传给它一个可调用的类实例 派生Thread的子类,并创建子类的实例 # There are three ways to create a thread # The first is create a thread instance, and pass a function # The second one

Python的线程&amp;进程&amp;协程[0] -&gt; 线程 -&gt; 多线程锁的使用

锁与信号量 目录 添加线程锁 锁的本质 互斥锁与可重入锁 死锁的产生 锁的上下文管理 信号量与有界信号量 1 添加线程锁 由于多线程对资源的抢占顺序不同,可能会产生冲突,通过添加线程锁来对共有资源进行控制. 1 import atexit 2 from random import randrange 3 from threading import Thread, Lock, current_thread # or currentThread 4 from time import ctime, s

Python的线程&amp;进程&amp;协程[1] -&gt; 线程 -&gt; 多线程的控制方式

多线程的控制方式 目录 唤醒单个线程等待 唤醒多个线程等待 条件函数等待 事件触发标志 函数延迟启动 设置线程障碍 1 唤醒单个线程等待 Condition类相当于一把高级的锁,可以进行一些复杂的线程同步控制.一般Condition内部都有一把内置的锁对象(默认为RLock),对于Condition的使用主要有以下步骤: 建立两个线程对象,及Condition对象; 线程1首先获取Condition的锁权限,acquire(); 线程1执行需要完成的任务后,调用等待wait(),此时,线程1会阻

Python的线程&amp;进程&amp;协程[2] -&gt; 进程 -&gt; 多进程的基本使用

多进程的基本使用 1 subprocess 常用函数示例 首先定义一个子进程调用的程序,用于打印一个输出语句,并获取命令行参数 1 import sys 2 print('Called_Function.py called, Hello world.') 3 try: 4 print('Got para', sys.argv[1:]) 5 except: 6 pass 再定义主函数,即父进程,分别测试 run() / call() / check_call() / getstatusoutput

python学习笔记-Day11 (线程、进程、queue队列、生产消费模型、携程)

线程使用 ###方式一 import threading def f1(arg): print(arg) t = threading.Thread(target=f1, args=(123,)) t.start() # start会调用run方法执行 # t是threading.Thread类的一个对象 # t.start()就会以线程的方式执行函数,可以使用pycharm ctrl选择start方法 # 找到Thread类的start方法,在start方法的注释中就已经写明,会去调用run()