python中线程的知识点

  1. 什么是线程?

    程序的执行线路。每个进程默认有一条线程。线程包含了程序的具体步骤。

    多线程就是一个进程中有除主线程(默认线程)外还有多个线程。

  2. 线程与进程的关系(进程包含线程,而线程依赖进程存在)

    1.进程包含了运行该程序的所有资源,是一个资源单位。

    2.线程是CPU的执行单位(最小的执行单位)。

    3.进程一旦被创建,就默认开启了一条线程,称之为主线程。

    4.线程共享创建它的进程的地址空间;进程有自己的地址空间。

    5.线程可以直接访问其进程的数据段;进程有它们自己的父进程的数据段副本。

    6.线程可以直接与进程的其他线程通信;进程必须使用进程间通信来与兄弟进程通信。

    7.容易创建新线程;新进程需要父进程的复制。

    8.线程可以对同一进程的线程进行相当大的控制;流程只能对子流程进行控制。

    9.对主线程的更改(取消、优先级更改等)可能会影响进程中其他线程的行为;对父进程的更改不会影响子进程。

  3. 为什么使用多线程?

    为了提高程序运行效率。与进程区别是线程对于系统资源的占用非常小。

    1.多个线程共享一个进程的地址空间。

    2.线程比进程对系统资源占用小,创建速度快10-100倍。

    3.同一个进程中多个线程之间资源共享,不需要像进程一样需要进程间通信。

  4. 线程的两种开启方式
    #第一种方式:导入threading模块中的Thread类来创建一个对象
    from threading import Thread
    ?
    def task():
        print(‘子线程 running。。。‘)
    t = Thread(target=task)
    t.start()
    print(‘over‘)
    # from threading import Thread
    #
    # def task():
    #     print(‘子线程 running。。。‘)
    #
    # if __name__ == ‘__main__‘:
    #     t = Thread(target=task)
    #     t.start()
    #     print(‘over‘)
    ?
    ?
    #第二种方式:创建一个子类继承Thread类,可自定义run方法,但是不能改变run方法名。
    from threading import Thread
    class MyThread(Thread):
        def __init__(self, name):
            super().__init__()
            self.name = name
        def run(self):
            print(‘%s say hi‘ % self.name)
    if __name__ == ‘__main__‘:
        t = MyThread(‘daidai‘)
        t.start()
  5. 进程和线程的对比
    from multiprocessing import Process
    from threading import Thread
    import time
    ?
    def task():
        pass
    #开启100个线程花费的时间
    start_time = time.time()
    ts = []
    for i in range(100):
        t = Thread(target=task)
        t.start()
        ts.append(t)
        print(os.getpid()) # 所有的进程编号都一样,同属一个进程中
    for t in ts:
        t.join()
    print(time.time()-start_time)
    ###
    0.018949270248413086
    ?
    #开启100个进程花费的时间
    if __name__ == ‘__main__‘:
        start = time.time()
        ps = []
        for i in range(100):
            p = Process(target=task)
            p.start()
            ps.append(p)
        for p in ps:
            p.join()
        print(time.time()-start)
     ###
    5.281934499740601
  6. 线程间的资源共享
    from threading import Thread
    x = 100
    def task():
        print("run....")
        global x  # 修改全局变量
        x = 0
    t = Thread(target=task)
    t.start()
    t.join() # join方法将子线程的优先级提高到主线程前
    print(x)
    print("over")
    ####
    run....
    0
    over
  7. 守护线程

    无论是进程还是线程:都遵循守护一方等待主方运行完毕后被销毁。运行完毕不是终止运行。

    1.对于主进程来说,运行完毕是主代码运行完毕。

    2.对于主线程来说,运行完毕是主线程内所有非守护线程运行完毕。所以守护线程会在所有非守护线程结束后结束。

    详细解释:

    #1.主进程在其代码结束后就已经算运行完毕(守护进程在此时会被回收),然后著京城会一直等着非守护的子进程都运行完毕后回收子进程的资源(否则就会产生僵尸进程),才会结束。

    #2.主线程在其他非守护线程运行完毕后才算运行完毕(守护线程在此时就会被回收)。因为主线程的结束意味着进程的结束,进程整体的资源都将被回收,而进程必须保证非守护线程都运行完毕后才能结束。

    ?
    from threading import Thread
    import time
    ?
    def task():
        print(‘sub thread running‘)
        time.sleep(3)
        print(‘sub thread over‘)
    ?
    t = Thread(target=task)
    t.setDaemon(True) # 要在开启之前设置
    t.start()
    print(‘main thread over‘)
    ###
    sub thread running
    main thread over
     
  8. Thread类对象常用的属性和方法

    对象的方法:

    isAlive():返回线程是否活动

    getName():返回线程名

    setName():设置线程名

    threading模块的一些方法:

    current_thread():返回当前线程变量,获取当前线程

    enumerate():返回一个包含正在运行线程的列表

    active_count():返回正在进行的线程数量,与len(threading.enumerate())有相同的结果。

    from threading import Thread,current_thread,enumerate,active_count
    import time
    import os
    def task():
        time.sleep(3)
        print(current_thread().getName())
    t = Thread(target = task)
    t.start()
    print(current_thread().getName())
    print(current_thread())
    print(enumerate())
    print(active_count())
    print(‘daidai‘)
    #运行结果
    MainThread
    <_MainThread(MainThread, started 14652)>
    [<_MainThread(MainThread, started 14652)>, <Thread(Thread-1, started 15548)>]
    2
    daidai
    Thread-1
    ?
    ?
    t.join()  #主线程等待子线程结束
    ?
  9. 线程互斥锁

    当多个进程或者多个线程需要同时修改同一份数据时,可能造成数据的错乱,所以需要给说句加上锁。

    同样的线程中也有死锁和可重入锁RLock

    import time
    from threading import Thread, Lock
    lock = Lock()
    a = 100
    def task():
        lock.acquire()
        global a  # 修改全局变量a
        temp = a-1
        time.sleep(0.05)
        a = temp
        lock.release()
    ts = []
    for i in range(100):
        t = Thread(target=task)
        t.start()
        ts.append(t)
    ?
    for t in ts:
        t.join()
    ?
    print(a)  # 全局中的a已经被修改为0
  10. 信号量Semaphore

    semaphore管理一个内置的计数器,每当调用acquire()时内置计数器-1:

    调用release()时内置计数器+1;

    计数器不能小于0;当计数器为0时,acquire()将阻塞线程直到其他线程调用release()。

    信号量其实也是一种锁,特点是可以设置一个数据可以被几个线程(进程)共享。

    与普通锁的区别:

    普通锁一旦加锁就意味着这个数据在同一时间只能被一个线程或进程使用。

    信号量可以让数据在同一时间能被多个线程使用。

    #实例:开启10个线程,每次运行3个
    from threading import Semaphore, Thread, current_thread
    import time
    ?
    sem = Semaphore(3)
    def task():
        sem.acquire()
        print(‘%s task running‘ % current_thread())
        time.sleep(3)
        sem.release()
    ?
    for i in range(10):
        t = Thread(target=task)
        t.start()
  11. 生产者消费者模型中的JoinableQueue

    JoinableQueue类是一种队列,Queue的子类。但是实例化的对象可以明确直到队列中是否有数据及数据的使用量。

    参数介绍:

    maxsize是队列中允许最大项数,省略则无大小限制。

    方法介绍:

    JoinableQueue的实例除了与Queue实例对象相同方法之外还有:

    task_done():使用者使用此方法发出信号,表示q.get()的返回项目已经被处理。如果调用此方法的次数大于从队列中删除项目的数量,将引发异常。

    q.join():明确生产者不会再生产数据。加入数据到队列中。

    import time
    import random
    from multiprocessing import Process, JoinableQueue
    def eat_hotdog(name, q):
        while True:
            res = q.get()
            if not res:
                print(‘吃完了。。。‘)
                break
            print(‘%s吃了%s‘ % (name, res))
            time.sleep(random.randint(1, 2))
            q.task_done() #向q.join()发送一次信号,证明一个数据已经被取走了
    def make_hotdog(name, q):
        for i in range(1,6):
            time.sleep(random.randint(1, 2))
            print(‘%s 生产了第%s个热狗‘ % (name,i))
            res = ‘%s的%s个热狗‘% (name,i)
            q.put(res)
    ?
    if __name__ == ‘__main__‘:
        q = JoinableQueue()
        #生产者1
        c1 = Process(target=make_hotdog, args=(‘万达‘, q))
        c1.start()
        #生产者2
        c2 = Process(target=make_hotdog, args=(‘呆呆‘, q))
        c2.start()
    ?
        p2 = Process(target=eat_hotdog, args=(‘思聪‘, q))
        p2.daemon = True
        p2.start()
    # 首先保证生产者全部产完成
        c1.join()
        c2.join()
    # 保证队列中的数据全部被处理了
        q.join()  # 明确生产方已经不会再生成数据了

原文地址:https://www.cnblogs.com/5j421/p/10597769.html

时间: 2024-10-17 18:40:37

python中线程的知识点的相关文章

python中线程和进程相关

1.操作系统/应用程序 a : 硬盘 , CPU , 主板 , 显卡 , 内存 , 电源 ... b.装系统 (软件) 系统就是一个由程序员写出来的软件 , 该软件用于控制计算机的硬件 , 让他们之间相互进行配合. c.安软件 (安装应用程序) QQ 百度云 pycharm .... 2.操作中的"并发"   ('并行') 并发 , 伪 , 由于执行速度特别快 , 人感觉不到停顿. 并行 , 真 , 创建10个人同时操作. 3.其他语言线程 , 进程 a. 单进程 , 单线程的应用程序

python中线程和进程(一)

目录 进程和线程 Python中的线程 1. Thread类 2. 线程的启动 3. 线程的传参 4. 线程的属性和方法 5. daemon线程和non-daemon线程 6. join方法 7. 定时器Timer 进程和线程 进程:进程是计算机中程序正在执行的实例,是系统进行资源分配和调度的基本单位. 线程:也被称为轻量级进程,是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针,寄存器集合和堆栈组成. 线程和进程的关系: 现代操作系统中,每一个进程都认为自己独占所有的计算机资源.进

python中的小知识点

1.想要获取当前时间需要使用time import time #引用time方法 Now_time = time.strftime('%Y-%m-%d %H:%M:%S') #输出当前的时间,格式是固定的,输入结果为2017-06-08 21:21:33 2.在文件写入的时候,想在文件中加入空格或者换行的话,格式如下: 其中Now_time是定义的变量.nathing是函数中传入的参数,是可以加引号的,他们之间使用+号进行连接 fl.write(Now_time+' '+nathing+'\n'

python中线程、进程和协程的区别

进程是资源分配的单位 线程是操作系统调度的单位 协程,又称微线程,纤程,协程的切换只是单纯的操作CPU的上下文,资源很小,效率高 进程切换需要的资源很最大,效率很低 一个程序至少有一个进程,一个进程至少有一个线程 线程执行开销小,但不利于资源的管理和保护:而进程正相反 通俗描述 有一个老板想要开个工厂进行生产某件商品(例如剪子) 他需要花一些财力物力制作一条生产线,这个生产线上有很多的器件以及材料这些所有的 为了能够生产剪子而准备的资源称之为:进程 只有生产线是不能够进行生产的,所以老板的找个工

Python中函数的知识点

1.函数的定义与调用 2.函数的参数 3.函数的返回值   1. 1.1.函数的定义: 函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段. 1.2.定义一个函数: 规则: 函数代码块以 def 关键词开头,后接函数标识符名称和圆括号().任何传入参数和自变量必须放在圆括号中间.圆括号之间可以用于定义参数.函数的第一行语句可以选择性地使用文档字符串-用于存放函数说明.函数内容以冒号起始,并且缩进.return [表达式] 结束函数,选择性地返回一个值给调用方.不带表达式的retur

Python:线程、进程与协程(7)——线程池

前面转载了一篇分析进程池源码的博文,是一篇分析进程池很全面的文章,点击此处可以阅读.在Python中还有一个线程池的概念,它也有并发处理能力,在一定程度上能提高系统运行效率:不正之处欢迎批评指正. 线程的生命周期可以分为5个状态:创建.就绪.运行.阻塞和终止.自线程创建到终止,线程便不断在运行.创建和销毁这3个状态.一个线程的运行时间可由此可以分为3部分:线程的启动时间.线程体的运行时间和线程的销毁时间.在多线程处理的情景中,如果线程不能被重用,就意味着每次创建都需要经过启动.销毁和运行3个过程

Python:线程、进程与协程(2)——threading模块(1)

上一篇博文介绍了Python中线程.进程与协程的基本概念,通过这几天的学习总结,下面来讲讲Python的threading模块.首先来看看threading模块有哪些方法和类吧. 主要有: Thread :线程类,这是用的最多的一个类,可以指定线程函数执行或者继承自它都可以实现子线程功能. Timer:与Thread类似,但要等待一段时间后才开始运行,是Thread的子类. Lock :原锁,是一个同步原语,当它锁住时不归某个特定的线程所有,这个可以对全局变量互斥时使用. RLock :可重入锁

Python 中的进程、线程、协程、同步、异步、回调(一)

一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说明一点术语.当我们说"上下文"的时候,指的是程序在执行中的一个状态.通常我们会用调用栈来表示这个状态--栈记载了每个调用层级执行到哪里,还有执行时的环境情况等所有有关的信息. 当我们说"上下文切换"的时候,表达的是一种从一个上下文切换到另一个上下文执行的技术.而"调度"指的是决定哪个上下文可以获得接下去的CPU时间的方法. 进程 进程是一种古老而典型的上下文系

Python 中的进程、线程、协程、同步、异步、回调

进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 在刚刚结束的 PyCon2014 上海站,来自七牛云存储的 Python 高级工程师许智翔带来了关于 Python 的分享<Python中的进程.线程.协程.同步.异步.回调>. 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说明一点术语.当我们说"上下文"的时候,指的是程序在执行中的一个状态.通常我们会用调用栈来表示这个状