关键词:
概要:
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 ‘ %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())
这里的异步概念是,默写的内容,已经默出来过的.
day849.threadlocal线程本地存储模式-java并发编程实战(代码片段)
ThreadLocal线程本地存储模式Hi,我是阿昌,今天学习记录的是关于ThreadLocal线程本地存储模式的内容。民国年间某山东省主席参加某大学校庆演讲,在篮球场看到十来个人穿着裤衩抢一个球,观之实在不雅,于... 查看详情
多线程之并发编程
学习链接Java并发教程 查看详情
并发编程之线程
一、线程概述1、什么是线程?线程依附进程而存在的,一个进程至少有一个线程,线程相当于微进程,多进程能实现并发,多线程也同样可以。线程是最小的执行单元。 2、线程的特点线程依附进程存在同一个进程中的线程... 查看详情
并发编程之线程属性
本文主要讨论线程的各种属性,包括:主线程、线程优先级、守护线程、线程组、处理未捕获异常的处理器。 主线程 任何一个Java程序启动时,至少会启动一个线程执行main方法,这个线程就被称为主线程(mainthr... 查看详情
并发编程路线
一python并发编程之多进程理论二python并发编程之多进程实现三python并发编程之多线程理论四python并发编程之多线程实现五python并发编程之协程理论六python并发编程之协程实现七python并发编程之IO模型五补充:paramiko模块 查看详情
重修课程day34(网络编程八之线程二)
一concurrent.futures模块 开启进程池和线程池模块。 线程池和进程池的区别:进程池开启的数量范围只能在CPU对的核数以内。而线程池的数量可以自己随便的定义,默认为是核数的五倍。 相关用法: ThreadPoolExecutor:创建... 查看详情
java并发编程之美之并发编程线程基础(代码片段)
什么是线程 进程是代码在数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,线程则是进程的一个执行路径,一个进程至少有一个线程,进程的多个线程共享进程的资源。 java启动main函数其实就是启动... 查看详情
day828.多线程原语:管程-java并发编程实战(代码片段)
多线程原语:管程Hi,我是阿昌,今天学习记录的是关于多线程原语:管程的内容。并发编程这个技术领域已经发展了半个世纪了,相关的理论和技术纷繁复杂。那有没有一种核心技术可以很方便地解决的并发... 查看详情
day828.多线程原语:管程-java并发编程实战(代码片段)
多线程原语:管程Hi,我是阿昌,今天学习记录的是关于多线程原语:管程的内容。并发编程这个技术领域已经发展了半个世纪了,相关的理论和技术纷繁复杂。那有没有一种核心技术可以很方便地解决的并发... 查看详情
并发编程之多线程
一、并发编程之多线程1、线程简单介绍进程是资源单位,把所有资源集中到一起,而线程是执行单位,真正执行的是线程每个进程都有一个地址空间,而且默认就有一个控制线程多线程:在一个进程中存在多个控制线程,多个... 查看详情
并发编程之线程与锁
线程是操作系统调度的最小单位,随着多核处理器的流行多线程编程成为能有效发挥cpu潜能的利器(python除外)。线程之间的内存是共享,所以创建一个线程所需要的开销比创建一个进程的开销要小得多。抛开硬件层面,多... 查看详情
原创java并发编程系列33|深入理解线程池(上)
【原创】Java并发编程系列33|深入理解线程池(上)收录于话题#并发编程238#程序员2286#java976#进阶架构师|并发编程专题12★★★建议星标我们★★★公众号改版后文章乱序推荐,希望你可以点击上方“Java进阶架构师”,点击右上... 查看详情
并发编程之线程多线程
线程开启线程的两种方法:#方式一:fromthreadingimport*importosdefwork():print(‘%sisworking‘%os.getpid())if__name__==‘__main__‘:t=Thread(target=work)t.start()方法1#方式二:classS_T(Thread):def__init__(self,name):super().__in 查看详情
多线程编程-之并发编程:阻塞队列
...urrentHashMap、CopyOnWriteArrayList),这些工具都为我们编写多线程程序提供了很大的方便。今天我们来讨论另外一类容器:阻塞队列。 在前面我们接触的队列都是非阻塞队列,比如PriorityQueue、LinkedList(LinkedList是双向链表,它实... 查看详情
多线程编程-之并发编程:同步容器
为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器、并发容器、阻塞队列、Synchronizer。同时说说List,Set,Map之间的区别. 自动扩展的数组:List 重复的数组:set 自动排序的组数:TreeSe... 查看详情
day863.协程-java并发编程实战(代码片段)
...的是关于协程的内容。Java语言里解决并发问题靠的是多线程,但线程是个重量级的对象,不能频繁创建、销毁,而且线程切换的成本也很高,为了解决这些问题,JavaSDK提供了线程池。然而用好线程池并不容易... 查看详情
day863.协程-java并发编程实战(代码片段)
...的是关于协程的内容。Java语言里解决并发问题靠的是多线程,但线程是个重量级的对象,不能频繁创建、销毁,而且线程切换的成本也很高,为了解决这些问题,JavaSDK提供了线程池。然而用好线程池并不容易... 查看详情
java并发编程系列之二线程基础
...文章对并发的理论基础进行了回顾,主要是为什么使用多线程、多线程会引发什么问题及引发的原因,和怎么使用Java中的多线程去解决这些问题。正所谓,知其然知其所以然,这是学习一个知识遵循的原则。推荐读者先行查看... 查看详情