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() # 明确生产方已经不会再生成数据了

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

  1. python中线程和进程(一)

    目录 进程和线程 Python中的线程 1. Thread类 2. 线程的启动 3. 线程的传参 4. 线程的属性和方法 5. daemon线程和non-daemon线程 6. join方法 7. 定 ...

  2. 操作系统/应用程序、操作中的“并发”、线程和进程,python中线程和进程(GIL锁),python线程编写+锁

    并发编程前言: 1.网络应用 1)爬虫 直接应用并发编程: 2)网络框架 django flask tornado 源码-并发编程 3)socketserver 源码-并发编程 2.运维领域 1)自动 ...

  3. python中线程和进程的简单了解

    python中线程和进程的简单了解   一.操作系统.应用程序 1.硬件:硬盘.cpu.主板.显卡........ 2.装系统(本身也是一个软件): 系统就是一个由程序员写出来的软件,该软件用于控制计 ...

  4. Python 中线程和进程

    目录 线程和进程 一. 什么是进程 / 线程 1. 引论 2. 线程 3. 进程 4. 区别 5. 使用 二. 多线程使用 1. 常用方法 2. 常用参数 3. 多线程的应用 3.1 重写线程法 3. ...

  5. python中的小知识点

    这里是一些小知识点的汇集,为的是以后查找的方便. 行与缩进: 物理行:实际看到的代码行数. 逻辑行:在意义上的函数(即解释器执行的行数) 如果一个物理行中包含了多个逻辑行,则每个逻辑行之间需要用分号 ...

  6. python中线程2

    cpython中的GIL和pool GIL锁(全局解释器锁) 1.what? GIL是全局解释器锁,和普通锁加在数据上不同的是:GIL加在加在解释器上,是为了防止多个线程在同一时间执行python字节 ...

  7. Python中线程的使用

    并发:多个任务同一时间段进行 并行:多个任务同一时刻进行 线程的实现 线程模块 Python通过两个标准库_thread 和threading,提供对线程的支持 , threading对_thread ...

  8. python中线程和进程(二)

    目录 线程同步 Event Lock RLock Condition Barrier semaphore GIL 线程同步 线程同步,即线程之间协同工作,一个线程访问某些数据时,其他线程不能访问这些数 ...

  9. Python中线程与互斥锁

    了解之前我们先了解一下什么是多任务? 概念: 几个不同的事件在同时运行就是多任务, 这样的话, 我们有牵扯到了真的多任务, 假的多任务; 并行: 真的多任务, 通过电脑的核数来确定 并发: 假的多任务 ...

随机推荐

  1. Beginning Math and Physics For Game Programmers (Wendy Stahler 著)

    Chapter 1. Points and Lines (已看) Chapter 2. Geometry Snippets (已看) Chapter 3. Trigonometry Snippets  ...

  2. Java面向对象和高级特性 项目实战(一)

    一.项目简介 项目名:嗖嗖移动业务大厅 技能点: 二.技能点 三.系统概述 四.整体开发思路 五.实体类和接口开发 六. 创建工具类 七.使用集合存储数据 八.开发计划 九.代码实现 1.项目目录 2 ...

  3. nginx添加ssl证书

    ssl的证书是通过docker nginx letsencrypt 这篇随笔生成的,下面介绍如何在nginx中添加ssl 这个为全部配置, 需要替换你自己的域名,配置中强制https了 server ...

  4. DNS 负载均衡

    相关文章: 文章 网址 一个域名可以绑定多个IP吗?由此引发的调查 https://ask.zkbhj.com/?/article/139

  5. C# 广告

    新建一个XML页面,设置属性 选择架构,勾选下面的目标,确定即可添加广告 广告模板: <?xml version="1.0" encoding="utf-8&quo ...

  6. 备份原有yum源,设置为自建yum源的脚本

    #脚本开始 #!/bin/bash cd /etc/yum.repos.d/ tar -zcvf yum.bak.tar.gz CentOS-* rm -rf CentOS* touch /etc/y ...

  7. 【转】Syncthing – 数据同步利器---自己的网盘,详细安装配置指南,内网使用,发现服务器配置

    Syncthing – 数据同步利器---自己的网盘,详细安装配置指南,内网使用,发现服务器配置 原贴:https://www.cnblogs.com/jackadam/p/8568833.html ...

  8. MySQL死锁分析一例

    Tomcat日志报死锁错误,show innodb status获取死锁信息: ------------------------ LATEST DETECTED DEADLOCK ---------- ...

  9. python3-基础6

    函数嵌套调用: 再调用一个函数的过程中,又调用了其他的函数 函数的嵌套定义:在一个函数的内部,又定义另外一个函数,函数内部定义的变量,在外部不能被调用 名称空间:一种隔离的概念,专门用来存放名字的地方 ...

  10. xxl-job源码分析

    1 调度中心API服务 1.任务结果回调服务: 2.执行器注册服务: 3.执行器注册摘除服务: 4.触发任务单次执行服务,支持任务根据业务事件触发: API暴露代码:com.xxl.job.admin ...