【python】-- 继承式多线程、守护线程

继承式多线程

1、定义

继承式多线程是自己自定义类,去继承theading.Tread这个类,通过类实例.start()启动,去执行run方法中的代码。

import threading
import time

class MyThread(threading.Thread):   # 继承threading.Thread
    """继承式多线程"""
    def __init__(self, n):
        threading.Thread.__init__(self)  # 也可以写成这样super(MyThread,self).__init__()
        self.n = n

    def run(self):     # 重写run方法
        """这个方法不能叫别的名字,只能叫run方法"""
        print("run", self.n)
        time.sleep(2)

t1 = MyThread("t1")   # 实例化
t2 = MyThread("t2")

t1.start()   # 启动一个多线程
t2.start()

2、通过for循环来启动线程

上面的例子只启动了一个2个线程,还是用那种古老的方式t1,t2。要是一下子起10个或者100个线程,这种方式就不适用了,其实可以在启动线程的时候,把它加到循环里面去,并且来计算一下它的时间:

这里设置成启动5个线程,并且计算一下时间。这里有个疑问,为什么不启动1000个线程或者更多一点的线程?这是因为:计算机是4核的,它能干的事情,就是4个任务。启动的线程越多,就代表着要在这个很多线程之间进行上下文切换。相当于教室里有一本书,某个人只看了半页,因为cpu要确保每个人都能执行,也就是这本是要确保教室每个同学都能看到,那就相当于每个人看书的时间非常少。也就是说某个同学刚刚把这本书拿过来,一下子又被第二个人,第三个人拿走了。所以就导致所有的人都慢了,所以说如果线程启动1000,启动10000就没有意义了,导致机器越来越慢,所以要适当设置

import threading,time

def run(n):   #这边的run方法的名字是自行定义的,跟继承式多线程不一样,那个是强制的
    print("task:",n)
    time.sleep(2)
    print("task done",n)

start_time = time.time()  #开始时间
for i in range(5):   #一次性启动5个线程
    t = threading.Thread(target=run,args=("t-{0}".format(i),))
    t.start()

print("--------all thead has finished")
print("cost:",time.time()-start_time)  #计算总耗时

#执行结果
task: t-0
task: t-1
task: t-2
task: t-3
task: t-4
--------all thead has finished
cost: 0.00096893310546875
task done t-1
task done t-2
task done t-0
task done t-4
task done t-3

从上面的程序发现,就是我主线程没有等其他的子线程执行完毕,就直接往下执行了,这是为什么呢?而且这个计算的时间根本不是我们想要的时间,中间的sleep 2秒哪里去了?

其实一个程序至少有一个线程,那先往下走的,没有等的就是主线程,主线程启动了子线程之后,子线程就是独立的,跟主线程就没有关系了。主线程和它启动的子线程是并行关系,这就解释了为什么我的主线程启动子线程之后,没有等子线程,而继续往下走了。所以计算不出来线程总共耗时时间,因为程序已经不是串行的了。程序本身就是一个线程,就是主线程。如果要想测试这五个线程总共花了多长时间,就需要用到线程的内置韩式join()

3、join设置等待线程执行结果

 3.1、通过设置在主线程里去等待子线程的执行结果,这里join()相当于wait的意思

import threading
import time

class MyThead(threading.Thread):
    "继承式多线程"
    def __init__(self,n):
        super(MyThead,self).__init__()
        self.n = n

    def run(self):
        "这个方法不能叫别的名字,只能叫run方法"
        print("runinit task",self.n)
        time.sleep(2)

t1 = MyThead("t1")
t2 = MyThead("t2")

t1.start()
t1.join()   #等待t1线程的执行结果,相当于于其他语言里面的 t1.wait()
t2.start()

注:

  1. t1.join()    等待第一个线程的执行结果,这个结果在没有返回之前,程序是不往下走的。所以这个程序变成串行的了。
  2. t2.start()   这个后面没有写 join() 这个方法,但是程序在退出之前,它肯定要确保线程都执行完毕,所以它就默认就有一个join()。

3.2、实现并发效果

上面虽然有想要的结果,却失去了并行的效果。如果想要的是线程依然是并行效果,就需要更换join()的位置了

流程图:

代码:

import threading
import time

class MyThread(threading.Thread):   # 继承threading.Thread
    """继承式多线程"""
    def __init__(self, n, sleep_time):  # 增加时间属性
        threading.Thread.__init__(self)  # 也可以写成这样super(MyThread,self).__init__()
        self.n = n
        self.sleep_time = sleep_time

    def run(self):     # 重写run方法
        print("run task", self.n)
        time.sleep(self.sleep_time)   # 每个线程可以传入不不同的时间
        print("task done,", self.n)

t1 = MyThread("t1", 2)   # 实例化
t2 = MyThread("t2", 4)

t1.start()   # 启动一个多线程
t2.start()

t1.join()  # 把t1.join()放在线程启动之后
print("main thread.....")

#执行结果
run task t1
run task t2
task done, t1
main thread.....
task done, t2

注:t1.join()    这边只等t1的结果,然后主线程继续往下走,因为t2需要等4秒,所以,最后打出来的是t2的执行结果。t1的结果到了,就立刻算结果。这边只计算了t1的结果,没有t2的结果

3.3 、计算多个线程的执行时间

重新改进一下第二点 “通过for循环来启动线程” 里面的代码,来计算一下10个线程启动执行的时间

import threading
import time

def run(n):  # 这边的run方法的名字是自行定义的,跟继承式多线程不一样,那个是强制的
    print("task:", n)
    time.sleep(2)
    print("task done", n)

start_time = time.time()  # 开始时间
t_obj = []  # 存放子线程实例
for i in range(10):  # 一次性启动10个线程
    t = threading.Thread(target=run, args=("t-{0}".format(i),))
    t.start()
    t_obj.append(t)   # 为了不阻塞后面线程的启动,不在这里join,先放到一个列表中

for t in t_obj:  # 循环线程实例列表,等待所有线程执行完毕
    t.join()  

print("--------all thread has finished")
print("cost:", time.time() - start_time)  # 计算总耗时

# 执行结果
task: t-0
task: t-1
task: t-2
task: t-3
task: t-4
task: t-5
task: t-6
task: t-7
task: t-8
task: t-9
task done t-2
task done t-1
task done t-0
task done t-3
task done t-4
task done t-5
task done t-6
task done t-9
task done t-8
task done t-7
--------all thread has finished
cost: 2.0067291259765625

这样主线程没有等其他的子线程执行完毕,才继续往下执行,就能测试出10个线程执行的总共耗时。

守护线程

上面的例子在不加join的时候,主线程和子线程完全是并行的,没有了依赖关系,主线程执行了,子线程也执行了。但是加了join之后,主线程依赖子线程执行完毕才往下走。

守护进程:

只要主线程执行完毕,它不管子线程有没有执行完毕。就退出了。现在就可以把所有的子线程变成守护线程。变成守护线程之后,主程序就不会等子线程结束载退出了。说白了,设置一个主人,在设置几个仆人,这几个仆人都是为主人服务的。可以帮主人做很多事情,一个主人(主线程)可以有多个仆人(守护线程),服务的前提是,主线程必须存在,如果主线程不存在,则守护进程也没了。那守护进程是干嘛的呢?可以管理一些资源,打开一些文件,监听一些端口,监听一些资源,把一些垃圾资源回收,可以干很多事情,可以随便定义。

1、守护线程设置

用setDaemon(True)来设置守护线程

import threading
import time

def run(n):
    print("task:", n)
    time.sleep(2)
    print("task done", n)

start_time = time.time()
for i in range(5):
    t = threading.Thread(target=run,args=("t-{0}".format(i),))
    t.setDaemon(True)  # Daemon意思是守护进程,这边是把当前线程设置为守护线程
    t.start()

print("--------all thread has finished")
print("cost:", time.time() - start_time)

#执行结果
task: t-0
task: t-1
task: t-2
task: t-3
task: t-4
--------all thread has finished
cost: 0.0010023117065429688

注:守护进程一定要在start之前设置,start之后就不能设置了,之后设置会报错,所以必须在start之前设置

2、使用场景

比如写一个socket_server,每一个链接过来,socket_server就会给这个链接分配一个新的线程。如果我手动的把socket_server停掉。那这种情况你必须手动停掉服务,那它就要down了,这种情况下还要等线程结束吗?就不用等线程结束了,它自己就直接结束了。这样,是不是就可以把每个socket线程设置一个守护线程,主线程一旦down掉,就全部退出。

3、知识点补充

查看当前线程和统计活动线程个数,用theading.current_thead()查看当前线程;用theading.active_count()来统计当前活动的线程数,线程个数=子线程数+主线程数

import threading,time

def run(n):
    print("task:",n)
    time.sleep(2)
    print("task done",n,threading.current_thread()) #查看每个子线程

start_time = time.time()
for i in range(5):
    t = threading.Thread(target=run,args=("t-{0}".format(i),))
    t.start()

print("--------all thead has finished",threading.current_thread(),threading.active_count())#查看主线程和当前活动的所有线程数
print("cost:",time.time()-start_time)

#执行结果
task: t-0
task: t-1
task: t-2
task: t-3
task: t-4
--------all thead has finished <_MainThread(MainThread, started 3840)> 6
cost: 0.0019359588623046875
task done t-0 <Thread(Thread-1, started 11536)>
task done t-3 <Thread(Thread-4, started 10480)>
task done t-2 <Thread(Thread-3, started 11008)>
task done t-4 <Thread(Thread-5, started 5088)>
task done t-1 <Thread(Thread-2, started 2464)>

  

时间: 2024-08-01 23:30:19

【python】-- 继承式多线程、守护线程的相关文章

python 并发编程 多线程 守护线程

做完工作这个进程就应该被销毁 单线程情况: 一个进程 ,默认有一个主线程 ,这个主线程执行完代码后 ,就应该自动销毁.然后进程也销毁. 多线程情况: 主线程代表进程结束 一个进程可以开多个线程,默认开启进程 ,首先开一个主线程 ,然后开子线程 ,主线程代码执行完毕后 ,也要等所有子线程 ,执行完毕后 ,再销毁 ,然后到进程销毁. 守护进程 要等主进程挂了后 守护进程才挂 1.对主进程来说,运行完毕指的是主进程代码运行完毕 2.对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完

6、第七周-网络编程-继承式多线程

Python threading模块介绍,threading 是 Python 高级别的多线程模块. threading 模块的函数 active_count() 当前活动的 Thread 对象个数 current_thread() 返回当前 Thread 对象 get_ident() 返回当前线程 enumerater() 返回当前活动 Thread 对象列表 main_thread() 返回主 Thread 对象 settrace(func) 为所有线程设置一个 trace 函数 setpr

java线程 - 多线程 - 守护线程

1.多线程可以实现Runnable接口或继承Thread,只能由Thread类的start()方法来启动一个线程 2.在Java中有两类线程:User Thread(用户线程).Daemon Thread(守护线程) 估计学过Unix开发但是没有细致学习Java的同学们会疑惑了,操作系统里面是没有所谓的守护线程的概念,只有守护进程一说,但是Java语言机制是构建在JVM的基础之上的,意思是Java平台把操作系统的底层给屏蔽起来,所以它可以在它自己的虚拟的平台里面构造出对自己有利的机制,而语言或者

多线程(守护线程、join方法、线程优先级、线程组)

setDaemon(boolean on): 守护线程(后台线程),若前台(显示)线程都结束了则后台线程自动结束. 使用setDaemon(boolean on)方法,必须在开启线程前将线程标记为守护线程. 示例: class setDaemon implements Runnable { public void run() { while (true) { System.out.println(Thread.currentThread().getName()+"...run"); }

java 多线程-守护线程

守护线程daemon,是为用户线程服务的,在start前设置默认情况下我们的线程是用户线程线程分为用户线程和守护线程虚拟机必须确保用户线程执行完毕虚拟机不用等待守护线程执行完毕如后台记录操作日志.监控内存使用等Thread对象.setDaemon(true);默认为false public class n { public static void main(String[]args) throws InterruptedException { test t=new test(); test2 t

python学习之-- 进程 和 线程

python 进程/线程详解 进程定义:以一个整体的形式暴露给操作系统管理,它里面包含对各种资源的调用,内存的管理,网络接口的调用等等,对各种资源管理的集合,就可以叫做一个进程. 线程定义:线程是操作系统能够进行运算调度的最小单位(是一串指令的集合).它被包含在进程之中,是进程中的实际运作单位.一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务. 另说明:进程是不能直接操作CPU执行的,每个进程的执行都是默认创建一个主线程来操作CPU进行执行指令集合

Python多线程的创建,相关函数和守护线程的理解

一:多线程的创建 threading库创建线程有两种方式,函数式和继承式    1)函数式 def func(): print 'Starting' print 'Ending' t=threading.Thread(name='func',target=func) t.start() 2)继承式 class ThreadClass(threading.Thread): def __init__(self, group = None, target = None, name = None, ar

python基础 多线程threading join 守护线程setDeamon 递归锁Rlock

开篇大概介绍多线程与多进程区别,详细的理论区别自己可以在其它博客搜一下,这里不再赘述 同一进程下的多个线程共享内存数据,多个线程之间没有主次关系,相互之间可以操作:cpu执行的都是线程,默认程序会开一个主线程:进程是程序以及和程序相关资源的集合:某些场景下我们可以使用多线程来达到提高程序执行效率的目的,下面就多线程的一些基础知识做简要说明 简单的多线程 1 import threading, time 2 3 def test1(x): 4 time.sleep(5) 5 print(x**x)

Python之路(第四十二篇)线程相关的其他方法、join()、Thread类的start()和run()方法的区别、守护线程

一.线程相关的其他方法 Thread实例对象的方法 # isAlive(): 返回线程是否活动的. # getName(): 返回线程名. # setName(): 设置线程名. ? threading模块提供的一些方法: # threading.currentThread(): 返回当前的线程对象. # threading.enumerate(): 返回一个包含正在运行的线程的list.正在运行指线程启动后.结束前,不包括启动前和终止后的线程. # threading.activeCount(