day33 网络编程之线程,并发

概要:

 1 并发编程需要掌握的知识点:
 2     开启进程/线程
 3     生产者消费者模型!!!
 4     GIL全局解释器锁(进程与线程的区别和应用场景)
 5     进程池线程池
 6
 7     IO模型(理论)
 8
 9
10 1 多线程
11     线程的概念?
12         一个进程内默认就会有一个控制线程,该控制线程可以执行代码从而创建新的线程
13         该控制线程的执行周期就代表改进程的执行周期
14     线程VS进程
15         1、线程的创建开销小于进程,创建速度快
16         2、同一进程下的多个线程共享该进程的地址空间
17     GIL全局解释器锁
18     线程池

开启线程的两种方式:

from threading import Thread
from multiprocessing import Process
import time,os

def task():
    print(‘%s is running‘ % os.getpid())
    time.sleep(5)
    print(‘%s is done‘ % os.getpid())

class Mythread(Thread):
    def __init__(self, name):
        super().__init__()
        self.name=name

    def run(self):
        print(‘%s is running‘ % os.getpid())
        time.sleep(5)
        print(‘%s is done‘ % os.getpid())

if __name__ == ‘__main__‘:
    # t=Thread(target=task,)
    # t=Process(target=task,)
    t=Mythread(‘xxxxx‘)
    t.start()

    print(‘主‘)
    ‘‘‘
    1、一个进程内不开子进程也不开“子线程”:主线程结束,该进程就结束

    2、当一个进程内开启子进程时:
        主线程结束,主进程要等,等所有子进程运行完毕,给儿子收尸

    3、当一个进程内开启多个线程时:
        主线程结束并不意味着进程结束,
        进程的结束指的是该进程内所有的线程都运行完毕,才应该回收进程
    ‘‘‘

这里需要注意一下,在线程里不存在僵尸线程和孤儿线程的概念.

进程和线程的区别:

#瞅一眼:PPID,PID
from threading import Thread
from multiprocessing import Process
import time,os

def task():
    print(‘partent:%s self:%s‘ %(os.getppid(),os.getpid()))
    time.sleep(5)

if __name__ == ‘__main__‘:
    t=Thread(target=task,)
    # t=Process(target=task,)
    t.start()

    print(‘主‘,os.getppid(),os.getpid())

#进程直接内存空间隔离
from threading import Thread
from multiprocessing import Process
import time,os

n=100
def task():
    global n
    n=0

if __name__ == ‘__main__‘:
    t=Process(target=task,)
    t.start()
    t.join()

    print(‘主‘,n)

#线程之间内存空间共享
from threading import Thread
import time,os

n=100
def task():
    global n
    n=0

if __name__ == ‘__main__‘:
    t=Thread(target=task,)
    t.start()
    t.join()

    print(‘主‘,n)

线程的其他属性以及方法:

from threading import Thread,current_thread,enumerate,active_count
import time,os

def task():
    print(‘%s is running‘ %current_thread().getName())
    time.sleep(5)
    print(‘%s is done‘ %current_thread().getName())

if __name__ == ‘__main__‘:
    # t=Thread(target=task,name=‘xxxx‘)  # # 这里有其他的参数就接着往后传即可,没有就只写一个函数名
    t=Thread(target=task)
    t.start()
    # print(t.name)

    #查看当前活着的线程
    print(enumerate()[0].getName())  # # MainThread  print(enumerate()[1].getName())------Thread-1
    # 这里有两个进程所以索引值就是只有0,1,超出部分会报错,out of range
    print(active_count())
    print(‘主‘,current_thread().getName())  # # 主 MainThread

线程池:

from concurrent.futures import ProcessPoolExecutor,ThreadPoolExecutor
from threading import current_thread
import time,random
def task(n):
    print(‘%s is running‘ %current_thread().getName())
    time.sleep(random.randint(1,3))
    return n**2

if __name__ == ‘__main__‘:
    # t=ProcessPoolExecutor() #默认是cpu的核数
    # import os
    # print(os.cpu_count())

    t=ThreadPoolExecutor(3) #默认是cpu的核数*5
    objs=[]
    for i in range(10):
        obj=t.submit(task,i)
        objs.append(obj)

    t.shutdown(wait=True)
    for obj in objs:
        print(obj.result())
    print(‘主‘,current_thread().getName())

这里有线程池的作业,我一并粘过来:

# 默写的内容是爬虫线程池的回调机制的代码
# socket 套接字用线程池的方式去写,然后再用多线程的方式去写
# 文本处理工具的三个任务先把一个套接字写出来然后看看怎么改成线程的概念
‘‘‘
以下则是开启多线程的方式:

from socket import *
from multiprocessing import Process
from threading import Thread
ser = socket(AF_INET, SOCK_DGRAM)
ser.bind((‘127.0.0.1‘, 3020))
ser.listen(2)
def connunicate(conn):
    while True:
        data = conn.recv()
        conn.send(data.upper())

if __name__ == ‘__main__‘:
    while True:
        conn, addr = ser.accept()

    t = Thread(target=connunicate, args=conn)
    t.start()
‘‘‘

‘‘‘
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import current_thread
import os
def task(n):
    print(‘%s is running‘ % current_thread().getName())

if __name__ == ‘__main__‘:
    t = ThreadProcessExecutor(12)
    # t = ProcessPoolExecutor(4)
    objs = []
    for i in range(20):
        obj = t.submit(task, i)
        objs.append(obj)

    t.shutdown(wait=True)
    for obj in objs:
        print(obj.result())
    print(‘主‘, os.getpid(), current_thread().getName())
‘‘‘

# 线程池的版本要理解后背下来!*****
# 开启线程池的方式:  这里是中级版本,已经搞定,功能都实现了,想要的结果都得到了!
from socket import *
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor
from threading import current_thread
import os

server = socket(AF_INET, SOCK_STREAM)
server.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)
server.bind((‘127.0.0.1‘, 5038))
server.listen(3)

def connunicate(conn,num):
    while True:
        data = conn.recv(1024)
        conn.send([data.upper(), os.getpid()])
        print(os.getpid())
    conn.close()

if __name__ == ‘__main__‘:
    t = ThreadPoolExecutor(12)
    objs = []
    while True:
        conn, addr = server.accept()
        tt = t.submit(connunicate, conn, os.getpid())
        objs.append(tt)
    # t.shutdown(wait=True)
    for ob in objs:
        print(ob.result())

    print(‘主‘, os.getpid())

# 客户端版本如下:
from socket import *

client=socket(AF_INET,SOCK_STREAM)
client.connect((‘127.0.0.1‘, 5038))

while True:
    msg=input(‘>>: ‘).strip()
    if not msg:continue

    client.send(msg.encode(‘utf-8‘))
    data=client.recv(1024)
    print(data.decode(‘utf-8‘))

以上的有需要补充的,那个文本操作没有写出来,把老师博客里面的代码粘过来,

from threading import Thread
msg_l=[]
format_l=[]
def talk():
    while True:
        msg=input(‘>>: ‘).strip()
        if not msg:continue
        msg_l.append(msg)

def format_msg():
    while True:
        if msg_l:
            res=msg_l.pop()
            format_l.append(res.upper())

def save():
    while True:
        if format_l:
            with open(‘db.txt‘,‘a‘,encoding=‘utf-8‘) as f:
                res=format_l.pop()
                f.write(‘%s\n‘ %res)

if __name__ == ‘__main__‘:
    t1=Thread(target=talk)
    t2=Thread(target=format_msg)
    t3=Thread(target=save)
    t1.start()
    t2.start()
    t3.start()

其实也好理解,就是自己没有多想一想,过早的放弃了.

异步概念补充(含回调函数):

# #pip install requests
# import requests
# from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
# from threading import current_thread
# import time
# import os
#
# def get(url):
#     print(‘%s GET %s‘ %(os.getpid(),url))
#     response=requests.get(url)
#     time.sleep(3)
#     if response.status_code == 200:
#         return {‘url‘:url,‘text‘:response.text}
#
# def parse(obj):
#     res=obj.result()
#     print(‘[%s] <%s> (%s)‘ % (os.getpid(), res[‘url‘],len(res[‘text‘])))
#
# if __name__ == ‘__main__‘:
#     urls = [
#         ‘https://www.python.org‘,
#         ‘https://www.baidu.com‘,
#         ‘https://www.jd.com‘,
#         ‘https://www.tmall.com‘,
#     ]
#     # t=ThreadPoolExecutor(2)
#     t=ProcessPoolExecutor(2)
#     for url in urls:
#         t.submit(get,url).add_done_callback(parse)
#     t.shutdown(wait=True)
#
#     print(‘主‘,os.getpid())

    # ‘‘‘
    # 异步调用:
    #     提交完任务(为该任务绑定一个回调函数),不用再原地等任务执行完毕拿到结果,可以直接提交下一个任务
    #     一个任务一旦执行完毕就会自动触发回调函数的运行
    #
    # 回调函数的参数是单一的:
    #     回调函数的参数就是它所绑定任务的返回值
    #
    # ‘‘‘

#pip install requests

import requests
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor
from threading import current_thread
import time
import os

def get(url):
    print(‘%s GET %s‘ %(current_thread().getName(),url))
    response=requests.get(url)
    time.sleep(3)
    if response.status_code == 200:
        return {‘url‘:url,‘text‘:response.text}

def parse(obj):
    res=obj.result()
    print(‘[%s] <%s> (%s)‘ % (current_thread().getName(), res[‘url‘],len(res[‘text‘])))

if __name__ == ‘__main__‘:
    urls = [
        ‘https://www.python.org‘,
        ‘https://www.baidu.com‘,
        ‘https://www.jd.com‘,
        ‘https://www.tmall.com‘,
    ]
    t=ThreadPoolExecutor(2)
    for url in urls:
        t.submit(get,url).add_done_callback(parse)
    t.shutdown(wait=True)

    print(‘主‘,os.getpid())

这里的异步概念是,默写的内容,已经默出来过的.

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

day33 网络编程之线程,并发的相关文章

python网络编程基础(线程与进程、并行与并发、同步与异步)

python网络编程基础(线程与进程.并行与并发.同步与异步) 目录 线程与进程 并行与并发 同步与异步 线程与进程 进程 前言 进程的出现是为了更好的利用CPU资源使到并发成为可能. 假设有两个任务A和B,当A遇到IO操作,CPU默默的等待任务A读取完操作再去执行任务B,这样无疑是对CPU资源的极大的浪费.聪明的老大们就在想若在任务A读取数据时,让任务B执行,当任务A读取完数据后,再切换到任务A执行.注意关键字切换,自然是切换,那么这就涉及到了状态的保存,状态的恢复,加上任务A与任务B所需要的

服务器端网络编程之线程模型

上一篇文章<服务器端网络编程之 IO 模型>中讲到服务器端高性能网络编程的核心在于架构,而架构的核心在于进程-线程模型的选择.本文将主要介绍传统的和目前流行的进程-线程模型,在讲进程-线程程模型之前需要先介绍一种设计模式: Reactor 模式,不明白的看这里<设计模式详解>,文中有一句话对 Reactor 模式总结的很好,引用下. Reactor 模式首先是事件驱动的,有一个或多个并发输入源,有一个Service Handler,有多个Request Handlers:这个Ser

网络编程进阶及并发编程

并发编程之多进程 进程理论 进程 进程:正在运行的一个过程或一个任务.负责执行任务的是cpu. 程序与进程的区别:程序只是一堆代码,而进程指的是程序的运行过程. 注意同一个程序执行两次,是两个进程.比如打开两个QQ,登陆的是不同人的QQ号. 并行与并发 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu, cpu来做这些任务,而一个cpu同一时刻只能执行一个任务. 并发:并发是看起来像是一起执行,实际上是通过在不同人物之间快速切换,使任务

《网络编程》线程

线程基本函数 当一个程序被启动时,只有一个主线程,若要实现对其他线程的基本操作,首先必须创建新的线程,新的线程创建可以使用 pthread_create 函数实现,该函数的 API 定义如下: /* 函数功能:创建新的线程: * 返回值:若成功则返回0,若出错则返回正的错误码: * 函数原型: */ #include <pthread.h> int pthread_create(pthread_t *tid, const pthread_attr_t *attr, void*(*func)(v

py2/py3区别, 列表生成式, 网络编程, socketserver, 线程, uuid模块

一. py2/py3区别    - 编码&字符串        字符串:            py2:                unicode         v = u"root"    本质上用unicode存储(万国码)                (str/bytes)     v = "root"     本质用字节存储            py3:                str                v = "

Python网络编程之线程与进程

What is a Thread? 线程是操作系统能够进行运算调度的最小单位,它被包含在进程之中,是进程中的实际运作单位,一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 在同一个进程内的线程的数据是可以进行互相访问的. 线程的切换使用过上下文来实现的,比如有一本书,有a和b这两个人(两个线程)看,a看完之后记录当前看到那一页哪一行,然后交给b看,b看完之后记录当前看到了那一页哪一行,此时a又要看了,那么a就通过上次记录的值(上下文)直接找到上次

网络编程进阶:并发编程之协程、IO模型

协程: 基于单线程实现并发,即只用一个主线程(此时可利用的CPU只有一个)情况下实现并发: 并发的本质:切换+保存状态 CPU正在运行一个任务,会在两种情况下切走去执行其他任务(切换有操作系统强制控制),一种情况是该任务发生了阻塞,另一种是该任务计算的时间过长或有一个优先级更高的程序替代了它 在介绍进程理论时,提及进程的三种执行状态,而线程才是执行单位,所以也可以将上图理解为线程的三种状态 如果多个任务都是纯计算的,上图的情况2并不能提升效率,因为只是让CPU来回切,这样看起来所有任务都被"同时

网络编程和线程

一.网络 (1)Unix 和 liunx是网络处理最好的操作系统. (2)网络必须要有网卡才能进行网络的连接. (3)原来网络走线方式,上网和电话线进入终端后一根线连接入户,这根线连接到数据分离器,分为ADLS端口和电话,再接收回来时,进过分离器传输到终端判断一下进入各自的线路. 二.网络分为广域网.城域网.局域网 中国最大的网络是国家骨干网,中国移动.联通.电信,都是靠骨干网分下来的网速. 1.广域网,在骨干网上拥有独立的IP地址. 2.城域网,一个城市所有联网用户共用一个IP地址. 3.局域

python网络编程-----&gt; socketserver实现并发

1.socketserver的作用: 基于tcp的套接字,关键就是两个循环,一个链接循环,一个通信循环 socketserver模块中分两大类:server类(解决链接问题)和request类(解决通信问题) 2.代码实现: 服务端: import socketserver class MyTcphandler(socketserver.BaseRequestHandler): def handle(self): while True: #通信循环 data=self.request.recv(