python程序 创建多线程过程详解


Posted in Python onSeptember 23, 2019

一、python线程的模块

1.1 thread和threading模块

thread模块提供了基本的线程和锁的支持

threading提供了更高级别、功能更强的线程管理的功能。

1.2 Queue模块

Queue模块允许用户创建一个可以用于多个线程之间共享数据的队列数据结构。

1.3注意模块的选择

  • 避免使用thread模块
  • 因为更高级别的threading模块更为先进,对线程的支持更为完善
  • 而且使用thread模块里的属性有可能会与threading出现冲突;
  • 其次低级别的thread模块的同步原语很少(实际上只有一个),而threading模块则有很多;
  • 再者,thread模块中当主线程结束时,所有的线程都会被强制结束掉,没有警告也不会有正常的清除工作,至少threading模块能确保重要的子线程退出后进程才退出。

注意:thread模块不支持守护线程,当主线程退出时,所有的子线程不论它们是否还在工作,都会被强行退出。而threading模块支持守护线程,守护线程一般是一个等待客户请求的服务器,如果没有客户提出请求它就在那等着,如果设定一个线程为守护线程,就表示这个线程是不重要的,在进程退出的时候,不用等待这个线程退出。

二、Threading模块

multiprocess模块的完全模仿了threading模块的接口,二者在使用层面,有很大的相似性,因而不再详细介绍(官方链接)

三、通过Threading.Thread类来创建线程

3.1 创建线程的方式一

1.直接通过Threading.Thread来创建

from threading import Thread
import time

def task(name):
  print(f'子线程{name} is running')
  time.sleep(1)
  print(f'子线程{name} is end')
  
# 因为创建线程不需要重新开辟内存空间,所以不用写main,创建线程只是单独把启动线程函数里面的代码拿出来用
t = Thread(target=task,args=('Cecilia陈',))
t.start()
print('主线程结束')

子线程Cecilia陈 is running

主线程结束

子线程Cecilia is end

3.2 创建线程的方式二

2.通过自定义类来继承Thread类来创建线程

from threading import Thread
import time
class MyDic(Thread,name):
  def __init__(self,name)
    super().__init__()
    self.name = name
  def run(self):
    print(f'子线程{name} is running')
    time.sleep(1)
    print(f'子线程{name} is end')
t = Mydic('Cecilia陈')
t.start()
print('主进程结束')

线程Cecilia陈 start

主进程

线程Cecilia陈 end

四、多线程和多进程的比较

4.1 pid的比较

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

def task(name):
  print(f'子线程{name} is running')
  time.sleep(1)
  print(f'子线程{name} is end')
  print(f'子线程{name}的pid:{os.getpid()}')
def task1(name):
  print(f'进程{name} is running')
  time.sleep(1)
  print(f'进程{name} is end')
  print(f'进程的{name}pid:{os.getpid()}')
if __name__ == '__main__':
  # part1:在主进程下开启多个线程,每个线程都跟主进程的pid一样
  t = Thread(target=task, args=('Cecilia陈',))
  t.start()
  t.join()
  print(f'主线程的pid:{os.getpid()}')
  # 开多个进程,每一个进程的pid号都不一样
  p = Process(target=task1,args=('xichen',))
  p1 = Process(target=task1,args=('xixi',))
  p.start()
  p1.start()
  p.join()
  p1.join()
  print(f'主进程的pid:{os.getpid()}')

子线程Cecilia陈 is running
子线程Cecilia陈 is end
子线程Cecilia陈的pid:10892
主线程的pid:10892
进程xixi is running
进程xichen is running
进程xichen is end
进程xixi is end
进程的xichenpid:6844
进程的xixipid:13700
主进程的pid:10892

4.2 线程和进程开启效率的较量

from threading import Thread
from multiprocessing import Process
import time
def task(name):
  print(f'{name} is running')
  time.sleep(2)
  print(f'{name} is end')
if __name__ == '__main__':
  t = Thread(target=task,args=('子线程',))
  p = Process(target=task,args=('子进程',))
  t.start()
  # p.start()
  print('主')

1.开启线程的速度:

子线程 is running

子线程 is end

2.开启进程的速度:

子进程 is running

子进程 is end

4.3 内存数据共享问题

from threading import Thread
from multiprocessing import Process
import time,os
x = 100
def task():
  global x
  x = 50 # 此时线程是在拿全局的x的值
  print(os.getpid()) # 因为开启线程是不需要操作系统给线程分配内存空间的,所以线程用的是它当前所在的进程的进程号
if __name__ == '__main__':
  # 线程
  t = Thread(target=task)
  t.start()
  time.sleep(2)
  print(x) # 50,这里说明线程他是共享他所在进程下的所有资源,对资源进行一系列的操作
  print(os.getpid())
  # 进程
  # p = Process(target=task)
  # p.start() 
  # print(x) # 这里的x还是主进程的x 100

五、Thread类的其他方法

Thread实例对象的方法:

  • isAlive():返回线程是否活动的。
  • getName():返回线程名。
  • setName():设置线程名。

threading模块提供的一些方法:

  • threading.currentThread():返回当前的线程变量。
  • threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  • threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。

5.1 代码实例

from threading import Thread,currentThread,enumerate,activeCount
import time

def task():
  print('子线程 start')
  time.sleep(2)
  print('子线程 end')
  print(enumerate())# 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
  print(currentThread(),'子线程') # 返回当前的线程变量
  print(activeCount())

if __name__ == '__main__':
  t1 = Thread(target=task)
  t2 = Thread(target=task)
  t1.start()
  t2.start()
  t2.setName('Cecilia陈')
  print(t2.getName()) # 得到t2的线程名字,是我们设置好的Cecilia陈
  print(t1.getName()) # 得到t1的线程名子 Thread-1
  print(t1.is_alive()) # True

5.2 join方法

from threading import Thread
import time
def task():
  print('子线程 start')
  time.sleep(2)
  print('子线程 end')

t = Thread(target=task)
t.start()
t.join() # 等待子线程运行结束
print('主线程')

六、多线程实现socket

6.1 服务端

import socket
from threading import Thread

socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
socket.bind(('192.168.11.78',8004))
socket.listen(5)

def action(conn,addr):
  while True:
    try:

      msg = (conn.recv(1024)).decode('utf8').upper()
      print(f'客户端{addr}发送的数据为:{msg.lower()}')
      print(f'向客户端{addr}发送数据为',msg)
      conn.send(msg.encode('utf8'))
    except:
      break
if __name__ == '__main__':
  print('等待客户端连接:')
  while True:
    try:
      conn,addr = socket.accept()
      print(f'客户端已连接{addr}')
      t = Thread(target=action,args=(conn,addr))
      t.start()
    except:
      print(f'客户端{addr}断开连接 !!')
      break

6.2 客户端

import socket
client = socket.socket()
client.connect(('192.168.11.78',8004))
while True:
  msg = input('输入:')
  if msg == 'q':
    break
  client.send(msg.encode('utf8'))
  flag = client.recv(1024)
  print('接收服务端的数据为:',flag.decode('utf8'))

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
用Python制作简单的钢琴程序的教程
Apr 01 Python
Python发送email的3种方法
Apr 28 Python
浅谈python抛出异常、自定义异常, 传递异常
Jun 20 Python
对python list 遍历删除的正确方法详解
Jun 29 Python
pytorch 转换矩阵的维数位置方法
Dec 08 Python
Python使用matplotlib实现交换式图形显示功能示例
Sep 06 Python
Python3基本输入与输出操作实例分析
Feb 14 Python
python GUI库图形界面开发之PyQt5布局控件QHBoxLayout详细使用方法与实例
Mar 06 Python
Pytorch十九种损失函数的使用详解
Apr 29 Python
PyQT5 实现快捷键复制表格数据的方法示例
Jun 19 Python
2021年值得向Python开发者推荐的VS Code扩展插件
Jan 25 Python
安装pytorch时报sslerror错误的解决方案
May 17 Python
详解python播放音频的三种方法
Sep 23 #Python
Python进程间通信 multiProcessing Queue队列实现详解
Sep 23 #Python
python程序中的线程操作 concurrent模块使用详解
Sep 23 #Python
Python3 pandas 操作列表实例详解
Sep 23 #Python
详解基于python-django框架的支付宝支付案例
Sep 23 #Python
如何利用Python开发一个简单的猜数字游戏
Sep 22 #Python
Python中关于浮点数的冷知识
Sep 22 #Python
You might like
for循环连续求和、九九乘法表代码
2012/02/20 PHP
php图片的裁剪与缩放生成符合需求的缩略图
2013/01/11 PHP
php简单开启gzip压缩方法(zlib.output_compression)
2013/04/13 PHP
使用PHP备份MYSQL数据的多种方法
2014/01/15 PHP
PHP实现清除wordpress里恶意代码
2015/10/21 PHP
Laravel利用gulp如何构建前端资源详解
2018/06/03 PHP
实例讲解PHP表单验证功能
2019/02/15 PHP
通过jQuery源码学习javascript(一)
2012/12/27 Javascript
jquery datatable后台封装数据示例代码
2014/08/07 Javascript
jQuery Ajax 全局调用封装实例代码详解
2016/06/02 Javascript
微信小程序一周时间表功能实现
2019/10/17 Javascript
使用React-Router实现前端路由鉴权的示例代码
2020/07/26 Javascript
python使用正则表达式的search()函数实现指定位置搜索功能
2017/11/10 Python
对python模块中多个类的用法详解
2019/01/10 Python
Python数据结构与算法(几种排序)小结
2019/06/22 Python
简单了解Django ContentType内置组件
2019/07/23 Python
Python-Flask:动态创建表的示例详解
2019/11/22 Python
pytorch中nn.Conv1d的用法详解
2019/12/31 Python
基于keras中的回调函数用法说明
2020/06/17 Python
使用Keras中的ImageDataGenerator进行批次读图方式
2020/06/17 Python
Django通过设置CORS解决跨域问题
2020/11/26 Python
世界上最大的餐具公司:Oneida
2016/12/17 全球购物
Yves Rocher伊夫·黎雪美国官网:法国始创植物美肌1959
2019/01/09 全球购物
啤酒销售实习自我鉴定
2013/09/24 职场文书
外语专业毕业生自我评价分享
2013/10/05 职场文书
专科毕业生就业推荐信
2013/11/01 职场文书
信息专业大学生自我评价分享
2014/01/17 职场文书
黄河象教学反思
2014/02/10 职场文书
教师节学生演讲稿
2014/09/03 职场文书
2014镇党委班子对照检查材料思想汇报
2014/09/23 职场文书
群众路线党员自我评议范文2014
2014/09/24 职场文书
付款委托书范本
2014/10/05 职场文书
公务员政审个人总结
2015/02/12 职场文书
学年个人总结范文
2015/03/05 职场文书
亮剑观后感300字
2015/06/05 职场文书
浅谈pytorch中的dropout的概率p
2021/05/27 Python