Python的Thread模块学习

前言:

对于除了主线程外的子线程来说,只有两种方法可以明确一个线程活动,传递一个回调函数给构造函数(直接传入要运行的方法),或者在子类中覆盖run方法。换句话说在Thread的子类中,只有run()和__init__()方法可以覆盖 。

背景


一般情况下针对不断循环调用的函数结构代码。

  • 背景一
    当我们不断的调用某个函数来执行某个动作时,可能由于调用的频繁导致上一次的调用还没有处理完,下一次的又调用了。这时,我们应该在调用这个函数的循环结构中,将调用函数的代码,采用的 方法一 为:换成调用Thread的代码,然后将要调用的函数传给Thread的target可选参数。方法二 为:重新继承Thread这个类,覆盖run方法,将要调用的代码移入Thread的run方法中
  • 背景二
    在一个主线程里,我们也可以将执行不同功能的函数都放入Thread线程中,让线程来启动执行这些动作。或者将不同的函数都重新继承一个线程,然后将函数的代码写入run方法中。

主线程


当一个进程启动之后,会默认产生一个主线程。main()函数启动一个进程进而产生一个主线程。

子线程


通过Threading模块的Thread()类新生成的示例,传入一个要运行的方法,或者覆盖改写子类中的run()方法来生成新线程。

主线程,子线程的关系


  • 当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束,例子见下面一。
  • 当我们使用setDaemon(True)方法,设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止,例子见下面二。
  • 当我们使用join()时,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,主线程一直等待全部的子线程结束之后,主线程自身才结束,程序退出。
    [t.join() for t in threads ]

socket.accept() & recv()方法


  • socket.accept( )阻塞线程的方法,如果没有accept,就一直阻塞线程。
  • socket.recv( )阻塞线程的方法,如果没有收到消息就一直阻塞线程

socket的Server端和Client端交流(send &recv)


  • 服务端必须生成多个ClientTheread来应对不同的客户端建立的连接,因为(conn,(ip,port)) = tcpServer.accept(),即一个客户端的连接,socket.accept()就返回一个 (conn,(ip,port))data = conn.recv(1024)用来接受客户端发送过来的消息data.decode("utf-8")来解码,conn.send(text.encode("utf-8"))用来向客户端编码并发送消息。
  • 一个客户端只用生成一个socket对象A,然后A.connect()之后就可以A.recv(1024)来接收服务器发送过来的数据,通过tcpClientA.send(text.encode("utf-8"))来向服务端发送编码好的消息。

线程生成方法


有两种方法来生成一个新的线程活动。第一种:通过要运行的回调对象传入Thread的构造函数。第二种:通过类的继承继承Thread类。然后覆盖Thread的run方法,将要执行的动作写入run方法中。而且只能覆盖run方法。最后调用方法start()来启动线程的状态。

  • 通过将要运行的代码编写为一个函数,然后将函数传入线程的初始化(即构造函数)表达式中
  • 实例一个线程对象,然后调用start方法,start方法会激活run方法进而执行run方法里的任务或行为。
newthread = ClientThread(ip,port,window)
newthread.start()

Thread.join()方法


join方法是用来确定线程是何时结束的。也就是将子线程与主线程绑定某种关系。主线程必须等待所有的join的子线程结束之后,才能结束。 join就是一个容器,如果里面的子线程都不结束,主线程是没有办法结束的。

初始状态:因为在同一个主进程中,如果有a,b进程start,那么它们开始的顺序是不按照代码的顺序执行的,这个是随机的。主线程开始,主线程结束,a,b随机先跑,随机先死。

  • 在线程a加入join之,就会等待a结束之后,才能将b进程加入,相当于给上面的随机现象排个队。执行顺序:主线程,a开始,a结束,主线程结束,b开始,b结束。
    在这里插入图片描述
  • a,b不知道谁先开始,a先死,主线程终止,b继续跑,跑完死;如果是b先死,那么a继续跑,跑完a死,主线程死。b没有join,所以和主线程无关。
    在这里插入图片描述
  • 主线程开始,a开始,a结束,b开始,b结束,主线程结束
    在这里插入图片描述

Thread对象


Once a thread object is created, its activity must be started by calling the thread’s start() method. This invokes the run() method in a separate thread of control.

  • 主线程。
  • 通过主线程来创造其他的子线程。
  • 线程n。
  • 线程没有terminate()函数(与进程的区别)。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值