Python 进程和线程

本文介绍了Python的进程和线程。通过代码示例展示了进程操作,包括进程池及其效率对比,以及事件、队列等同步机制。同时,讨论了进程与线程的区别,如进程创建时间长、线程创建时间短,以及它们在CPU调度和资源共享上的差异。多线程适合需要内存共享的异步任务,而多进程适用于数据隔离的场景。
摘要由CSDN通过智能技术生成
# 特别简单
# 进程
# 操作系统发展
    # 没有操作系统 —— 穿孔卡片
    # 批处理系统  —— 串行 ,速度块
        #   联机批处理 读磁带的时候速度快
        #   脱机批处理 读磁带和cpu工作并发
    # 多道程序系统 —— 并行
        #   操作系统的各种管理功能
        #   时空的复用 : 空间隔离开来,cpu看起来可以处理多个任务
    # 分时系统 —— 更好的实现了 并行
        #   让cpu的工作效率下降了
    # 实时系统 —— 对一个任务实时响应
        # 优点 快
        # 缺点 能处理的任务更少
    # 通用操作系统
        # 兼具多个操作系统的特性

# 操作系统的功能
    # 封装了对硬件的操作过程,给应用程序提供好用的接口
    # 对多个作业进行调度管理来分配硬件资源

# 进程
    #  程序
    #  只有在运行当中的程序 —— 进程
    #  操作系统和进程的关系
    #  为什么要引入进程的概念
    #     隔离资源
    # 进程是操作系统中资源分配的最小单位

    # 进程是怎么被调度的呢?
        # 先来先服务算法 FCFS
        # 短作业优先算法
        # 时间片轮转算法
        # 多级反馈算法
            # 进程Process
            # 1 = [p2,p3,p4,p5,p7]
            # 2 = [p1,p2,p3]
            # 3 = [p6]
    # 现代的操作系统中

# 进程
    # 异步  只管调度 不等结果
    # 同步  调度之后 还一定要等到结果

    # 异步 我拿一个号
    # 同步

    # 阻塞
    # 非阻塞
    # —— 影响进程的调度

# 进程的状态 : 就绪 运行 阻塞
# 进程的创建与结束
    # 创建进程有很多方式 —— 就是让一个程序运行起来
    # 所有的进程都是被进程创建出来的
    # 父进程 子进程

    # 进程的结束

Python进程代码示例如下:

# import os
# import time
# print(os.getpid())  # 获取当前运行的python程序的进程id  process id
# print(os.getppid()) # parent process id 获取当前进程的父id
# time.sleep(100)

# python当中创建进程来替我做事情
# multiprocess模块
# 综合的 处理进程的 包
# multi 多元的综合
# process 进程

# Process 和创建进程相关
# import os
# import time
# from multiprocessing import Process
# # def func(money):
# #     time.sleep(3)
# #     print('取钱 :%d'%money)
#
# # if __name__ == '__main__':
# #     p = Process(target=func,args=(1,))    # 创建一个进程对象
# #     p.start()   # 直到执行start才有了进程
# #     print('去取钱')
# #     p.join()   # 阻塞
# #     print('取完钱了')
# # 在同一个进程中 程序确实是从上到下依次进行
# # 阻塞 程序又阻塞了
#
# # 创建进程对象 传要执行的函数 以及参数
# # 进程对象.start()
# # 主进程和子进程就是异步执行
# # 如果主进程中的代码已经结束了,子进程还没结束,主进程会等待子进程
#
# # p.join 就是主进程会阻塞在join的位置,等待p进程结束
# # windows操作系统中 创建进程的语句一定要放在if __name__ == '__main__':条件语句下面
#
# # 开启多个子进程
# # import os
# # import time
# # from multiprocessing import Process
# # def func(i):
# #     time.sleep(1)
# #     print('%d :子进程%d干的事儿,父进程:%d'%(i,os.getpid(),os.getppid()))
# #
# # if __name__ == '__main__':
# #     # 100
# #     p_lst = []
# #     for i in range(10):
# #         p = Process(target=func,args=(i,))
# #         p.start()
# #         p_lst.append(p)
# #     for p in p_lst:p.join()
# #     print('------主进程------')
#
# # 另一种开启进程的方式
# # 通过继承
# # import os
# # from multiprocessing import Process
# # class MyProcess(Process):
# #     def run(self):
# #         print('子进程:%d'%os.getpid())
# #         self.walk()  # --->在子进程中调用
# #
# #     def walk(self): # 自定义的 可以不定义
# #         print('子进程:%d' % os.getpid())
# #
# # if __name__ == '__main__':
# #     p = MyProcess()
# #     p.start()    # --->  run方法
# #     # p.walk()     # --->  在主进程中调用
# #     print('主进程 :',os.getpid())
#
# # 必须创建一个类 必须继承Process类
# # 必须实现一个run方法
#
# # 调用阶段
# # 先实例化一个对象
# # 对象.start()
#
#
# import os
# from multiprocessing import Process
# # class MyProcess(Process):
# #     def __init__(self,arg1,arg2):
# #         super().__init__()
# #         self.arg1 = arg1
# #         self.arg2 = arg2
# #
# #     def run(self):
# #         print('子进程:%d,%s,%s'%(os.getpid(),self.arg1,self.arg2))
# #         self.walk()  # --->在子进程中调用
# #
# #     def walk(self): # 自定义的 可以不定义
# #         print('子进程:%d' % os.getpid())
# #
# # if __name__ == '__main__':
# #     p = MyProcess(1,2)
# #     p.start()    # --->  run方法
# #     # p.walk()     # --->  在主进程中调用
# #     print('主进程 :',os.getpid())
#
# # 数据隔离
# # 进程与进程之间的数据是共享的
# from multiprocessing import Process
# n = 100
# def func():
#     global n
#     n = n - 1
#     print(n)
# if __name__ == '__main__':
#     for i in range(10):
#         p = Process(target=func)
#         p.start()
#         p.join()
#     print('主进程 :',n)

import os
from multiprocessing import Process
class MyProcess(Process):
    def __init__(self,arg1,arg2,arg3):
        super().__init__()
        self.arg1 = arg1
        self.arg2 = arg2
        self.arg3 = arg3
    def run(self):
        print('子进程 : ',os.getpid(),self.arg1,self.arg2,self.arg3)
        self.walk()  # walk方法会在子进程中执行

    def walk(self):
        print('子进程 : ',os.getpid())

if __name__ == '__main__':
    p = MyProcess(1,2,3)
    p.start()   # 会默认调用run方法
    p.walk()    # walk方法直接在主进程中调用 并没有在子进程中执行
    print('主进程 :',os.getpid())

# 必须创建一个类 必须继承Process类
# 必须实现一个run方法

# 实例化MyProcess得到一个对象
# 使用对象调用start方法

#

进程操作实例和其它进程的方法

#server.python
import socket;
from multiprocessing import Process;

def talk(conn):
    conn.send(b'connected')
    ret = conn.recv(1024)
    print(ret)

if __name__ == "__main__":
    sk = socket.socket();
    sk.bind(("127.0.0.1", 8081));
    sk.listen();
    while True:
        conn, addr = sk.accept();
        p = Process(target=talk, args=(conn,));
        p.start();
    conn.close();
    sk.close();
#client.python
import socket;

sk = socket.socket();
sk.connect(('127.0.0.1', 8081));
ret = sk.recv(1024);
print(ret);
inp = input(">>>");
sk.send(inp.encode('utf-8'));

sk.close();
# start 开启一个进程
# join 让主进程等待子进程结束
#
# 守护进程
# 守护进程会随着主进程的结束而结束
# 如果子进程没有执行完,主进程要一直等着
# 守护进程中不能再开启子进程

import time;
from multiprocessing import Process;

def func():
    print("-"*10);

def cal_time():
    # p = Process(target=func);
    # p.start();
    while True:
        time.sleep(1);
        print('过去了1秒');
if __name__ == "__main__":
    p = Process(target=cal_time);
    p.daemon = True #一定要在开启之前设置
    p.start();
    for i in range(100):
        time.sleep(0.1)
        print("*"*i);
import time;
from multiprocessing import Process;
def func():
    print("wahaha");
    time.sleep(5);
    print('qqxing');

if __name__ == "__main__":
    p = Process(target=func);
    p.start();
    print(p.is_alive());#进程是否存在
    time.sleep(0.1);
    p.terminate();#结束一个进程
    print(p.is_alive());
    time.sleep(2);
    print(p.is_alive());
import time;
from multiprocessing import Process;
def func():
    print("wahaha");
    time.sleep(5);
    print('qqxing');

if __name__ == "__main__":
    p = Process(target=func);
    p.start();
    print(p.is_alive());#进程是否存在
    time.sleep(0.1);
    print(p.name, p.pid);#查看进程名字和id
    p.name = "zhongzheng";
    print(p.name)

    p.terminate();#结束一个进程
    print(p.is_alive());
    time.sleep(2);
    print(p.is_alive());
import time;
from multiprocessing import Process;
class MyProcess(Process):
    def run(self):
        print('wahaha', self.name, self.pid);
        time.sleep(5);
        print('qqxing', self.name, self.pid);

if __name__ == "__main__":
    p = MyProcess();
    p.start();
    print("pid:", p.pid);
# from multiprocessing import Lock;
# lock = Lock()
#
# lock.acquire(); #需要锁,拿钥匙
# # lock.acquire(); #需要锁,阻塞
# lock.release(); #释放锁,还钥匙

# 锁就是在并发编程中 保证数据安全

from multiprocessing import Lock;
from multiprocessing import Process;
import time;
import json;
import random;

def search():
    with open('ticket') as f:
        print(json.load(f)['count']);

def get(i):
    with open('ticket') as f:
        ticket_num = json.load(f)['count'];
    time.sleep(random.random());

    if ticket_num > 0:
        with open('ticket', 'w') as f:
            json.dump({'count': ticket_num-1}, f);
        print("%s买到票了"%i);

    else:
        print("%s没票了"%i);
def task(i, lock):
    search();
    lock.acquire();
    get(i);
    lock.release();

if __name__ == "__main__":
    lock = Lock();
    for i in range(20):
        p = Process(target=task, args=(i, lock));
        p.start();
from multiprocessing import Process;
from multiprocessing import Semaphore;
import random;
import time;

def sing(i, sem):
    sem.acquire();
    print("%s: 进入 ktv"%i);
    time.sleep(random.randint(0, 10));
    print("%s: 出 ktv"%i);
    sem.release();

if __name__ == '__main__':
    sem = Semaphore(4);
    for i in range(20):
        Process(target=sing, args=(i, sem)).start();
#生产者消费者模型.py
import time;
import random;
from multiprocessing import Queue;
from multiprocessing import Process;

def producer(q, food):
    for i in range(5):
        q.put('%s-%s'%(food,i))
        print("生产了%s"%food);
        time.sleep(random.random());

    q.put(None)
    q.put(None)
    q.put(None)

def consumer(q, name):
    while True:
        food = q.get();
        if food == None:break;
        print("%s吃了%s"%(name, food));

if __name__ == "__main__":
    q = Queue();
    p1 = Process(target=producer, args=(q, "泔水"));
    p1.start();
    p2 = Process(target=producer, args=(q, "甜水"));
    p2.start();
    c1 = Process(target=consumer, args=(q, "alex"));
    c1.start();
    c2 = Process(target=consumer, args=(q, "老三"));
    c2.start();
    c3 = Process(target=consumer, args=(q, "老二"));
    c3.start();

# 队列安全
# 生产者消费者模型
#     1.消费者要处理多少数据是不确定的
#     2.所能只能用while循环来处理数据,while循环无法结束,
#     3.需要生产者发送信号
#     4.有多少个消费者,就需要发送多少个信号
#     5.但是发送的信号数量需要根据生产者和消费者的数量进行计算,所以非常不便

# put q.join
# get 处理数据 task_done消费完了

import time;
import random;
from multiprocessing import JoinableQueue;
from multiprocessing import Process;

def producer(q, food):
    for i in range(5):
        q.put('%s-%s'%(food,i))
        print("生产了%s"%food);
        time.sleep(random.random());

    q.join();

def consumer(q, name):
    while True:
        food = q.get();
        if food == None:break;
        print("%s吃了%s"%(name, food));
        q.task_done();

if __name__ == "__main__":
    q = JoinableQueue();
    p1 = Process(target=producer, args=(q, "泔水"));
    p1.start();
    p2 = Process(target=producer, args=(q, "甜水"));
    p2.start();

    c1 = Process(target=consumer, args=(q, "alex"));
    c1.daemon = True;
    c1.start();

    c2 = Process(target=consumer, args=(q, "老三"));
    c2.daemon = True;
    c2.start();

    c3 = Process(target=consumer, args=(q, "老二"));
    c3.daemon = True;
    c3.start();

    p1.join() #等待p1执行完毕
    p2.join() #等待p2执行完毕

#生产者生产的数据全部被消费 ————生产者进程结束————主进程代码执行结束——消费者守护进程
# ipc机制——队列
# ipc机制——管道

from multiprocessing import Pipe;
p1, p2 = Pipe();#支持双向通信管道

p1.send('hello');
print(p2.recv());

p2.send('hi');
p2.close()
print(p1.recv());
print(p1.recv());

#关于管道: 双方通信
# ipc机制——队列
# ipc机制——管道

# from multiprocessing import Pipe;
# p1, p2 = Pipe();#支持双向通信管道
#
# p1.send('hello');
# print(p2.recv());
#
# p2.send('hi');
# p2.close()
# print(p1.recv());
# print(p1.recv());

#关于管道: 双方通信
from multiprocessing import Process;
from multiprocessing import Pipe

def func(p):
    foo, son = p;
    foo.close();
    print(son.recv());

if __name__ == '__main__':
    foo, son = Pipe();
    p = Process(target=func, args=((foo, son),));
    p.start();
    son.close();
    foo.send('hello');
    foo.close();
# ipc机制——队列
# ipc机制——管道

# from multiprocessing import Pipe;
# p1, p2 = Pipe();#支持双向通信管道
#
# p1.send('hello');
# print(p2.recv());
#
# p2.send('hi');
# p2.close()
# print(p1.recv());
# print(p1.recv());

#关于管道: 双方通信
from multiprocessing import Process;
from multiprocessing import Pipe
from multiprocessing import Lock;

def func2(p):
    foo, son = p;
    son.close();
    for i in range(10):
        foo.send(i);
    foo.close();

def func(p, lock):
    foo, son = p;
    foo.close();
    while True:
        try:
            lock.acquire();
            print(son.recv());
            lock.release();
        except EOFError:
            lock.release();
            son.close();
            break;

if __name__ == '__main__':
    lock = Lock();
    foo, son = Pipe();
    p1 = Process(target=func, args=((foo, son), lock));
    p1.start();
    p2 = Process(target=func, args=((foo, son), lock));
    p2.start();

    p3 = Process(target=func2, args=((foo, son), ));
    p3.start();
    p4 = Process(target=func2, args=((foo, son), ));
    p4.start();

    son.close();
    foo.close();

#队列 = 管道+锁 安全
#进程之间数据不安全,没有锁的机制
# Manager是一个类,提供了可以进行数据共享的一个机制,提供了很多数据类型 dict list
from multiprocessing import Manager;

if __name__ == '__main__':
    m = Manager();
    d = m.dict();
    print(d);
    d['count'] = 0;
    print(d);
#同步
from multiprocessing import Manager,Process;

def work(d):
    print(d);
    d['count'] -= 1;

if __name__ == '__main__':
    m = Manager();
    dic = m.dict({'count':100});
    for i in range(100):
        p = Process(target=work, args=(dic,));
        p.start();
        p.join(); #等待子进程结束
#异步
from multiprocessing import Manager
from multiprocessing import Process, Lock;

def func(d, lock):
    # print(d)
    lock.acquire();
    d["count"]-=1
    lock.release();

if __name__=="__main__":
    lock = Lock();
    m=Manager()
    d=m.dict({"count":10})
    l=[]  # 存放开启的进程
    for i in range(10):
        p=Process(target=func,args=(d, lock))
        p.start()
        # p.join()   # 判断该子进程是否结束,结束了才会继续开下一个进程(所以这样就会变成同步的)
        l.append(p)  # 把开启的进程放在列表中
    [p.join() for p in l]  # 把刚才开的10个进程放在列表,该语句执行代表开的10个进程全部结束
    print(d)

# Manager dict list pipe 并不提供数据安全支持

进程池

# 进程能无限开吗
    # cpu 16核处理16个任务

    # 160个进程/16 10*0.01
# 不能无限开

# 开启一个进程的时候
    # 要给进程分配资源,分配内存

#值 数据结构 字典

#100个任务
#4核 --开4个进程 完成100个任务叫——进程池
#第五个任务进来, 占用进程,执行任务

#进程池
# 造一个池子,放4个进程用来完成工作
#发任务
#循环使用池子中的进程来完成任务

from multiprocessing import Pool;
import os;
import time;
import random;

def fun(i):
    print(i, os.getpid());
    time.sleep(random.randint(1, 3));

# print(os.cpu_count());
if __name__ == "__main__":
    p = Pool(5);
    p.map(fun, range(20));
    p.close();#不允许再向进程池中添加任务
    print('--->')

进程池与开多个进程执行时间 对比

#进程为什么出现:开过多的进程
#作用:1.开启过多进程浪费时间;2.操作系统调用太多的进程也会影响效率
from multiprocessing import Pool, Process;

import time;


def fun(i):
    i += 1;

# print(os.cpu_count());
if __name__ == "__main__":
    p = Pool(5);
    start = time.time();
    p.map(fun, range(20));#map(函数,可迭代)
    p.close();#不允许再向进程池中添加任务
    p.join();
    print(time.time() - start);

    #创建多个进程
    start = time.time();
    l = [];
    for i in range(100):
        p = Process(target=fun, args=(i,));
        p.start();
        l.append(p);
    [i.join() for i in l]
    print(time.time() - start);

效果如下:

 

from multiprocessing import Pool;
import time;
def func(i):
    time.sleep(1);
    i += 1;
    # print(i);
    return i+1;

if __name__ == "__main__":
    p = Pool(5);
    rel_l = [];
    for i in range(20):
        # p.apply(func, args=(i, ))#apply是同步提交任务的机制
        ret = p.apply_async(func, args=(i,))#apply_async是异步提交任务的机制
        rel_l.append(ret);
        # print(ret.get()); #阻塞:等待着任务结果

    p.close();#必须有 close必须在join()之前,不允许再添加新的任务了
    p.join();#必须有 等待子进程结束再往下执行

    [print(i.get()) for i in rel_l]

事件

# from multiprocessing import Event;
# e = Event();#实例化一个事件 标志/交通信号灯/默认是红灯
# e.set();  #将标志变成非阻塞/交通灯变绿
# e.wait(); #刚实例化出来的一个事件对象,默认的信号是阻塞信号/默认是红灯
#           #执行到wait,要先看灯,绿灯行红灯停,如果在停的过程中灯绿了,就变成非阻塞了
#
# e.clear() #将标志又变成阻塞/交通灯变红
#
# e.is_set() #看这个事件是否阻塞,True就是绿灯,False是红灯

import time;
import random;
from multiprocessing import Event, Process;


def traffic_light(e):
    while True:
        if e.is_set():
            time.sleep(3);
            print('红灯亮');
            e.clear();
        else:
            time.sleep(3);
            print("绿灯亮");
            e.set();#红灯变绿灯
def car(i, e):
    e.wait();
    print("%s车通过"%i);

if __name__ == "__main__":
    e = Event();
    p = Process(target=traffic_light, args=(e,));
    p.start();

    for i in range(100):
        if i%6 == 0:
            time.sleep(random.randint(1, 3));

        car_pro = Process(target=car, args=(i, e))
        car_pro.start();

队列

# from multiprocessing import Queue;
# q = Queue();
# q.put(1);
# q.put(2);
# q.put(3);
#
# print(q.get());
# print(q.get());
# print(q.get());
# print(q.get());#如果队列里已经没有值了,就会阻塞等待一个有值

# 进程之间通信可以使用Queue模块
#队列创建有两种方式,一种不传参数,队列没有长度限制;传参数,创建一个最大长度限制
#提供两个重要方法:put get
#qsize

from multiprocessing import Queue;
from multiprocessing import Process;

def q_put(q):
    q.put("hello");

def q_get(q):
    print(q.get());

if __name__ == "__main__":
    q = Queue();
    p = Process(target=q_put, args=(q,));
    p.start();
    p1 = Process(target=q_get, args=(q,));
    p1.start();

#通过队列实现了主进程与子进程的通信,子进程与子进程之间的通信
#生产者消费者模型
#我要生产一个数据然后给一个函数,让这个函数依赖这个数据进行运算,拿到结果 ——同步过程 

 

from multiprocessing import Queue;
from multiprocessing import Process;
import time;

def producer(q):#生产者
    for i in range(100):
        q.put("包子%s"%i);

def consumer(q):#消费者
    for i in range(100):
        time.sleep(1);
        print(q.get());

if __name__ == "__main__":
    q = Queue(10);#托盘
    p = Process(target=producer, args=(q,));
    p.start();
    c = Process(target=consumer, args=(q,));
    c.start();
    c2 = Process(target=consumer, args=(q,));
    c2.start();

#对于内存空间来说,每次只有很少的数据会在内存中
#对于生产与消费之间的不平衡来说
    # 增加消费者或生产者来调节效率

 

import requests;
ret = requests.get("http://www.baidu.com")
print(ret);
print(ret.text);#整个网页的源代码
print(ret.status_code);#状态码

 

# 进程之间的通信 IPC
# 队列 生产者消费者模型 *****
# joinablequeue 队列可以感知到数据的处理 taskdone q.join()
# Pipe 管道
# Manager模块里面又提供了很多数据类型来进行进程之间的数据共享,但是几乎数据都不安全
# def func(dic,lock):
#     lock.acquire()
#     dic['count'] += 1
#     lock.release()
#     print(dic)   #
#
# m = Manager()
# dic = m.dict()
# dic['count'] = 0
# lock = Lock()
# for i in range(100):
#     p = Process(target=func,args=(dic,lock))
#     p.start()
# p.join()


# 进程池
# 进程池为什么出现 :开过多的进程 1.开启进程浪费时间 2. 操作系统调度太多的进程也会影响效率
# 开进程池 : 有几个现成的进程在池子里,有任务来了,就用这个池子中的进程去处理任务,
              # 任务处理完之后,再把进程放回池子里,池子中的进程就能去处理其他任务了。
              # 当所有的任务都处理完了,进程池关闭,回收所有的进程
# 开的进程数 :cpu_count + 1
# import time
# from multiprocessing import Pool
# def fun(i):
#     time.sleep(1)
#     i+=1
#     return i
#
# if __name__ == '__main__':
#     p = Pool(4)
#     res_l = []
#     for i in range(10):
#         res = p.apply_async(fun,args=(i,))   #apply 是同步调用 顺序执行代码 target
#         res_l.append(res)
#     p.close()   # 不能再往进程池中添加新的任务
#     p.join()    # 阻塞等待 执行进程池中的所有任务直到执行结束
#     # apply_async是一个异步调用
#     # 和主进程也异步了
#     [print(res.get()) for res in res_l]  # 异步调用获取函数的返回值

# import time
# from multiprocessing import Pool
# def fun(i):
#     time.sleep(1)
#     i+=1
#     return i
# if __name__ == '__main__':
#     s = time.time()
#     p = Pool(4)
#     ret = p.map(fun,range(10))    # func(next(range(10)))
#     print(ret)
#     print(time.time() - s)

# apply  apply_async  map

# import os
# import time
# from multiprocessing import Pool
# # 参数 概念 回调函数
# def func(i):    # 多进程中的io多,
#     print('子进程%s:%s'%(i,os.getpid()))
#     return i*'*'
#
# def call(arg):   # 回调函数是在主进程中完成的,不能传参数,只能接受多进程中函数的返回值
#     print('回调 :',os.getpid())
#     print(arg)
#
# if __name__ == '__main__':
#     print('---->',os.getpid())
#     p = Pool(5)
#     for i in range(10):
#         p.apply_async(func,args=(i,),callback=call)
#     p.close()
#     p.join()

# 例子
# 请求网页
    # 网络延时 IO操作
# 单进程
    # 10个页面  同时访问多个   —> 多进程
    # 分析页面:长短  ——>回调函数
# from urllib.request import urlopen
import requests
from multiprocessing import Pool
def get_url(url):
    ret = requests.get(url)
    return {'url':url,
            'status_code':ret.status_code,
            'content':ret.text}

def parser(dic):
    print(dic['url'],dic['status_code'],len(dic['content']))
    # 把分析结果写到文件里
# if __name__ == '__main__':
#     url_l = [
#         'http://www.baidu.com',
#         'http://www.sogou.com',
#         'http://www.hao123.com',
#         'http://www.yangxiaoer.cc',
#         'http://www.python.org'
#     ]
#     p = Pool(4)
#     for url in url_l:
#         p.apply_async(get_url,args=(url,),callback=parser)
#     p.close()
#     p.join()

# pool(4)
# 如何使用进程池  —— 都可以那到返回值
# apply 同步调用 直接调用之后就获得返回值
# apply_async 异步调用
    # 在完成所有进程调用之后,close表示不再接受新任务
    # join 让主进程等待子进程执行结束
    # 如果需要获得返回值,提交任务之后返回的对象.get()就可以获取返回值
    # callback 回调函数 :主进程执行 参数是子进程执行的函数的返回值
# map(func,iterable)






Python线程

进程是资源分配最小的单位,线程是cpu调度最小的单位,每个进程中至少有一个线程。

进程和线程的关系

1.多进程开启进程的时间长,多线程开启线程的时间短

2.cpu在进程之间的切换慢,cpu在进程之间的切换快

#如果两个任务,需要共享内存,又想实现异步,使用多线程

#如果两个任务,数据需要隔离,使用多进程 

多线程的好处:轻量级且同一个进程之间的多个线程资源是共享的 

内存中的线程

 

# 进程   执行中的程序
# 线程   轻量级的进程

# 进程可以处理一个任务
# 听课 + 记笔记 + 看屏幕

# 进程 一个时间点 只能做一件事
# 三个进程 听课 记笔记 看屏幕

# 对于一个人 来说 一个人就是一个进程
# 一个人可以做的多件事情 每一件事都是一个线程

# 进程包含着线程
# GIL  全局解释器锁 Cpython解释器
# 去掉GIL 保证数据安全 细粒度的锁 效率更低

# 高计算 多进程
# 高IO   多线程  —— 爬虫 网络

# 线程 更加的轻量级
# 线程是CPU调度的最小单位
# 进程是资源分配的最小单位

# 开启线程的时空开销 都比 开启进程要小
# 且 cpu在线程之间切换 比 在进程之间切换快

# 一个程序中 可以同时有多进程和线程
# import os
# import time
# from threading import Thread
#
# def func():    # 子线程
#     time.sleep(1)
#     print('hello world',os.getpid())
# thread_lst = []
# for i in range(10):
#     t = Thread(target=func)
#     t.start()
#     thread_lst.append(t)
# [t.join() for t in thread_lst]
# print(os.getpid())   # 主线程

# import os
# import time
# from threading import Thread
#
# class MyThread(Thread):
#     count = 0         # 静态属性
#     def __init__(self,arg1,arg2):
#         super().__init__()
#         self.arg1 = arg1
#         self.arg2 = arg2
#     def run(self):
#         MyThread.count += 1
#         time.sleep(1)
#         print('%s,%s,%s,%s'%(self.arg1,self.arg2,self.name,os.getpid()))
#
# for i in range(10):
#     t = MyThread(i,i*'*')
#     t.start()
# print(t.count)
# 计算开启的线程数量
# 多个子线程 共享 这个数据
import time
import threading
def func(i):
    time.sleep(0.5)
    print(i,threading.currentThread().name,threading.currentThread().ident)
    # ident 线程id
for i in range(10):
    t = threading.Thread(target=func,args=(i,))
    t.start()

# print(len(threading.enumerate()))  # 返回正在运行着的线程列表
print(threading.activeCount())

# 作业
# 1.开进程池回调函数 把分析结果写进文件里
# 2.用多线程实现socket并发的server
    # 仿照多进程
# 复习
# 函数 面向对象 网络编程 并发编程

 

#server.py
import socket;
from threading import Thread;

def func(conn):
    conn.send(b'hello');
    ret = conn.recv(1024);
    print(ret);
    conn.close();

sk = socket.socket();
sk.bind(('127.0.0.1', 8080));
sk.listen();

while True:
    conn, addr = sk.accept();
    Thread(target=func, args=(conn,)).start();

 

import socket;

sk = socket.socket();
sk.connect(('127.0.0.1', 8080));

ret = sk.recv(1024);
print(ret);
msg = input('>>>');
sk.send(msg.encode('utf-8'));
sk.close();

线程锁

import time
from threading import Thread
from threading import Lock
def func():
    global n
    time.sleep(2)
    lock.acquire()
    temp = n   # 从进程中获取n
    time.sleep(0.01)
    n = temp-1 # 得到结果,再存储回进程
    lock.release()

n = 100
lock = Lock()
t_lst = []
for i in range(100):
    t = Thread(target=func)
    t.start()
    t_lst.append(t)
[t.join() for t in t_lst]
print(n)

# GIL 不是锁数据 而是锁线程
# 在多线程中 特殊情况 仍然要加锁 对数据
# 慢 join lock

线程信号量

# 信号量
# 事件
# 条件
# 定时器
# 队列
import time
import random
from threading import Thread
from threading import Semaphore
def func(n,sem):
    sem.acquire()
    print('thread -%s start'%n)
    time.sleep(random.random())
    print('thread -%s done' % n)
    sem.release()
sem = Semaphore(5)   # 一把锁有5把钥匙
for i in range(20):
    Thread(target=func,args=(i,sem)).start()

# 信号量 和 线程池 有什么区别?
# 相同点 在信号量acquire之后,和线程池一样 同时在执行的只能有n个
# 不同点
    # 开的线程数不一样 线程池来说 一共就只开5个线程 信号量有几个任务就开几个线程
# 对有信号量限制的程序来说 可以同时执行很多线程么?
# 实际上 信号量并不影响线程或者进程的并发,只是在加锁的阶段进行流量限制

线程事件

# Event
# flag 标志
# 刚刚创建的时候 flag = False
# wait() flag=False 阻塞
        #flag = True 非阻塞
# set()  False --> True
# clear()  True --> False

# 连接mysql数据库
# 我连接三次数据库
# 每0.5秒连接一次
# 创建一个事件 来标志数据库的连接情况
# 如果连接成功,就显示成功
# 否则 就报错 主动抛异常TimeoutError
import time
import random
from threading import Event
from threading import Thread
def conn_mysql():  # 连接数据库
    count = 1
    while not e.is_set():  # 当事件的flag为False时才执行循环内的语句
        if count>3:
            raise TimeoutError
        print('尝试连接第%s次'%count)
        count += 1
        e.wait(0.5)  # 一直阻塞变成了只阻塞0.5
    print('连接成功')  # 收到check_conn函数内的set指令,让flag变为True跳出while循环,执行本句代码

def check_conn():
    '''
    检测数据库服务器的连接是否正常
    '''
    time.sleep(random.randint(1,2))  # 模拟连接检测的时间
    e.set() # 告诉事件的标志数据库可以连接

e = Event()
check = Thread(target=check_conn)
check.start()
conn = Thread(target=conn_mysql)
conn.start()



线程队列

import queue
# q = queue.Queue()   # 队列 线程安全的
# q.get()
# q.put()
# q.qsize()

# lfq = queue.LifoQueue()  # 后进先出  :栈
# lfq.put(1)
# lfq.put(2)
# lfq.put(3)
# lfq.put(4)
# print(lfq.get())
# print(lfq.get())
# print(lfq.get())
# print(lfq.get())
# []
import queue
pq = queue.PriorityQueue()  # 值越小越优先,值相同就asc码小的先出
pq.put((1,'z'))
pq.put((1,'b'))
pq.put((15,'c'))
pq.put((2,'d'))
#
print(pq.get())
print(pq.get())

# 线程版本的生产者消费者模型 多线程+Queue —— 作业

 

import time
import random
from concurrent import futures
def funcname(n):
    print(n)
    time.sleep(random.randint(1,3))
    return n*'*'
def call(args):
    print(args.result())
thread_pool = futures.ThreadPoolExecutor(5)
# thread_pool.map(funcname,range(10))  # map,天生异步,接收可迭代对象的数据,不支持返回值
# f_lst = []
# for i in range(10):
#     f = thread_pool.submit(funcname,i)   # submit 合并了创建线程对象和start的功能
#     f_lst.append(f)
# thread_pool.shutdown()  # close() join()
# for f in f_lst:         # 一定是按照顺序出结果
#     print(f.result())   #f.result()阻塞 等f执行完得到结果

# 回调函数 add_done_callback(回调函数的名字)
thread_pool.submit(funcname,1).add_done_callback(call)
# 统一了入口和方法 简化了操作 降低了学习的时间成本


# 作业一 —— 线程版本的生产者消费者模型 多线程+Queue
# 作业二 —— 爬取网页 线程池实现

# 4核
# 进程4-5个+线程 20个线程  = 100


    # 线程池 和 进程池
# 是用来做池操作的最近新的模块

# 开启线程需要成本 成本比开启进程要低
# 高IO的情况下 开多线程
# 所以我们也不能开启任意多个线程
# 开启线程池

# futures.ThreadPoolExecutor    # 线程池
# futures.ProcessPoolExecutor   # 进程池


# 进程池 cpu个数 + 1
# 线程池 默认 :cpu个数 * 5   4核*5  20个线程

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值