标签:encoding 返回 方式 sed targe write lob xxx 空间
阅读目录
什么是线程
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程
线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程
车间负责把资源整合到一起,是一个资源单位,而一个车间内至少有一个流水线
流水线的工作需要电源,电源就相当于cpu
所以,进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位。
多线程(即多个控制线程)的概念是,在一个进程中存在多个控制线程,多个控制线程共享该进程的地址空间,相当于一个车间内有多条流水线,都共用一个车间的资源。
例如,北京地铁与上海地铁是不同的进程,而北京地铁里的13号线是一个线程,北京地铁所有的线路共享北京地铁所有的资源,比如所有的乘客可以被所有线路拉。
线程的特点,为什么用多线程
多线程指的是,在一个进程中开启多个线程,简单的讲:如果多个任务共用一块地址空间,那么必须在一个进程内开启多个线程。详细的讲分为4点:
1. 多线程共享一个进程的地址空间
2. 线程比进程更轻量级,线程比进程更容易创建和撤销,在许多操作系统中,创建一个线程比创建一个进程要快10-100倍,在有大量线程需要动态和快速修改时,这一特性很有用
3. 若多个线程都是cpu密集型的,那么并不能获得性能上的增强,但是如果存在大量的计算和大量的I/O处理,拥有多个线程允许这些活动彼此重叠运行,从而会加快程序执行的速度。
4. 在多cpu系统中,为了最大限度的利用多核,可以开启多个线程,比开进程开销要小的多。(这一条并不适用于python)
开启线程 threading模块
1.开启线程的两种方式
#方式一 from threading import Thread import time def sayhi(name): time.sleep(2) print(‘%s say hello‘ %name) if __name__ == ‘__main__‘: t=Thread(target=sayhi,args=(‘egon‘,)) t.start() print(‘主线程‘)
#方式二 from threading import Thread import time class Sayhi(Thread): #继承父类Thread def __init__(self,name): #可以定义自己的初始属性 super().__init__() #继承父类的__init__方法 self.name=name def run(self): #开启线程执行run里的内容 time.sleep(2) print(‘%s say hello‘ % self.name) if __name__ == ‘__main__‘: t = Sayhi(‘egon‘) t.start() print(‘主线程‘)
2.在一个进程下开启多个线程与在一个进程下开启多个子进程的区别
1-开启线程的速度更快
2-在主进程下开启多个线程,每个线程都跟主进程的pid一样
from threading import Thread from multiprocessing import Process import os def work(): print(‘hello‘,os.getpid()) if __name__ == ‘__main__‘: #part1:在主进程下开启多个线程,每个线程都跟主进程的pid一样 t1=Thread(target=work) t2=Thread(target=work) t1.start() t2.start() print(‘主线程/主进程pid‘,os.getpid()) #part2:开多个进程,每个进程都有不同的pid p1=Process(target=work) p2=Process(target=work) p1.start() p2.start() print(‘主线程/主进程pid‘,os.getpid())
3-同一进程内的线程共享该进程的数据
from threading import Thread from multiprocessing import Process import os def work(): global n n=0 if __name__ == ‘__main__‘: # n=100 # p=Process(target=work) # p.start() # p.join() # print(‘主‘,n) #毫无疑问子进程p已经将自己的全局的n改成了0,但改的仅仅是它自己的,查看父进程的n仍然为100 n=1 t=Thread(target=work) t.start() t.join() print(‘主‘,n) #查看结果为0,因为同一进程内的线程之间共享进程内的数据
3.实例
1-实例一 :多线程并发的套接字通讯
#_*_coding:utf-8_*_ #!/usr/bin/env python import multiprocessing import threading import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.bind((‘127.0.0.1‘,8080)) s.listen(5) def action(conn): while True: data=conn.recv(1024) print(data) conn.send(data.upper()) if __name__ == ‘__main__‘: while True: conn,addr=s.accept() p=threading.Thread(target=action,args=(conn,)) p.start()
#_*_coding:utf-8_*_ #!/usr/bin/env python import socket s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((‘127.0.0.1‘,8080)) while True: msg=input(‘>>: ‘).strip() if not msg:continue s.send(msg.encode(‘utf-8‘)) data=s.recv(1024) print(data)
2-实例二 :三个任务,一个接收用户输入,一个将用户输入的内容格式化成大写,一个将格式化后的结果存入文件
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()
4.线程相关的其他方法
Thread实例对象的方法 # isAlive(): 返回线程是否活动的。 # getName(): 返回线程名。 # setName(): 设置线程名。 threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程变量。 # threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。 # threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
from threading import Thread,current_thread,enumerate,activeCount import os,time n=100 def work(): print(‘%s is ruuning‘ %current_thread().getName()) if __name__ == ‘__main__‘: t=Thread(target=work) t.start() t.join() print(t.is_alive()) #判断线程是否存货 print(t.getName()) #获得线程名字 print(current_thread().getName()) #获取主线程名字 print(enumerate()) #返回一个列表,有哪些活跃的线程 print(activeCount()) #活跃线程的数量 print(‘主线程‘,n)
主线程等待子线程结束
from threading import Thread import time def sayhi(name): time.sleep(2) print(‘%s say hello‘ %name) if __name__ == ‘__main__‘: t=Thread(target=sayhi,args=(‘egon‘,)) t.start() t.join() print(‘主线程‘) print(t.is_alive()) ‘‘‘ egon say hello 主线程 False ‘‘‘
5.守护线程
无论是进程还是线程,都遵循:守护xxx会等待主xxx运行完毕后被销毁
需要强调的是:运行完毕并非终止运行
#1.对主进程来说,运行完毕指的是主进程代码运行完毕 #2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
详细解释:
#1 主进程在其代码结束后就已经算运行完毕了(守护进程在此时就被回收),然后主进程会一直等非守护的子进程都运行完毕后回收子进程的资源(否则会产生僵尸进程),才会结束, #2 主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。
from threading import Thread import time def sayhi(name): time.sleep(2) print(‘%s say hello‘ %name) if __name__ == ‘__main__‘: t=Thread(target=sayhi,args=(‘egon‘,)) t.daemon = True #必须在t.start()之前设置 t.start() print(‘主线程‘) print(t.is_alive()) ‘‘‘ 主线程 True ‘‘‘
from threading import Thread import time def foo(): print(123) time.sleep(1) print("end123") def bar(): print(456) time.sleep(3) print("end456") t1=Thread(target=foo) #设置线程 t2=Thread(target=bar) #设置线程 t1.daemon=True #把t1设置成守护线程 t1.start() #开启线程 t2.start() #开启线程 print("main-------") # 打印结果 # 123 # 456 # main------- # end123 #主线程必须在所有非守护线程结束后才结束,主线程运行完后就不再等守护线程结束,因为主线程结束时守护线程已经结束,所以先打印end123,再打印end456 # end456
>>>详细介绍
标签:encoding 返回 方式 sed targe write lob xxx 空间
原文地址:http://www.cnblogs.com/zhoujunhao/p/7662789.html