zoukankan      html  css  js  c++  java
  • 多线程

    多线程

    一、概念

    1、多线程 ​ 什么是线程 ​ 程序的执行线路 ​ 相当于与一条流水线,其包含了程序的具体执行步骤 ​ 如果我们把操作系统比喻为一个工厂,进程就是车间,先出就是流水线

    2、线程和进程的关系 ​ 进程中包含了运行改程序需要所有资源, 进程是一个资源单位,线程是CPU的最小执行单位 ​ 每一个进程一旦被创建.就默认开启了一条线程,称之为主线程 ​ 一个进程可以包含多个线程 ​ 进程包含线程 而 线程依赖进程

    3、为什么使用线程 ​ 是为了提高程序效率, ​ 为何不用多进程提高效率? 是因为进程对操作系统的资源耗费非常高

    4、线程是如何提高效率的? ​ 多线程可以使CPU在一个进程内进行切换,从而提高CPU占用率

    5、如何使用 ​ 两种开启线程的方式 ​ 1.实例化Thread类 ​ 2.继承Thread类 覆盖run方法

    6、什么情况下应该开启多线程 ​ 当程序中遇到IO的时候 ​ 当程序中时纯计算任务时 也无法提高效率

    7、进程和线程的区别 ​ 1.进程对于操作系统的资源耗费非常高,而线程相反非常低(比进程低10-100倍) ​ 2.在同一个进程,多个线程之间资源是共享的

    二、线程资源共享

    举例:

    from threading import Thread
    x = 10
    def task():
       print("run....")
       global x
       x = 0
    t = Thread(target=task)
    t.start()
    t.join()

    print(x)
    print("over")

    三、守护线程

    守护线程会在所有非守护线程结束后结束

    进程 守护进程会在被守护进程死亡跟着死亡

    同一个进程 可以有多个守护线程

    from threading import Thread
    import time

    def task():
       print("子线程运行。。。")
       time.sleep(1)
       print("子线程结束。。。")
    t = Thread(target=task)
    t.setDaemon(True)

    t.start()
    # time.sleep(0.1)
    print("over")

    四、线程中的常用属性

    from threading import Thread,current_thread,enumerate,active_count
    import os
    def task():
       print("running..")
       # print(os.getpid())
       # print(current_thread())
       print(active_count())

    t1 = Thread(target=task)
    t1.start()
    # print(t1.is_alive())
    # print(t1.isAlive())
    # print(t1.getName())

    # 获取所有线程对象列表
    print(enumerate())
    # 获取当前线程对象
    print(current_thread())
    # 获取当前正在运行的线程个数
    print(active_count())

    # t2 = Thread(target=task)
    # t2.start()

    五、线程互斥锁

    什么时候用锁 当多个进程或多个线程需要同时修改同一份数据时,可能会造成数据的错乱,所以

    必须得加锁

    import time
    from threading import Thread,Lock
    lock =Lock()
    a = 100
    def task():
       lock.acquire()
       global a
       temp = a - 1
       time.sleep(0.01)
       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)

    六、信号量

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

    与普通锁的区别

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

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

    使用场景,可以限制一个数据被同时访问的次数,保证程序正常运行

    from threading import Semaphore,Thread,current_thread
    import time,random
    sem = Semaphore(3)
    def task():
       sem.acquire()
       print("%s run..." % current_thread())
       time.sleep(3)
       sem.release()

    for i in range(10):
       t = Thread(target=task)
       t.start()

    七、守护进程与生产者消费者模型

    import time,random
    from multiprocessing import Process,JoinableQueue
    def eat_hotdog(name,q):
       while True:
           res = q.get()
           print("%s吃了%s" % (name,res))
           time.sleep(random.randint(1,2))
           q.task_done() #记录已经被处理的数据的数量

    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)
       # q.put(None)

    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.start()

       # 首先保证生产者全部产完成
       c1.join()
       c2.join()

       # 保证队列中的数据全部被处理了
       q.join() # 明确生产方已经不会再生成数据了

     

  • 相关阅读:
    vs2008 当前上下文不存在名称xxx 解决办法
    SQL Server 2008故障转移集群+数据库镜像配置实例之一
    通过JavaScript获取页面大小
    使用JavaScript判断浏览器类型
    sql2008安装图解sql2008安装全过程
    Sqlserver中对时间类型的字段转换
    SQL Server 2008故障转移集群+数据库镜像配置实例之三
    这年头口罩都成时尚品
    一位软件工程师的6年总结[转]
    MS SQL Server查询优化方法[转]
  • 原文地址:https://www.cnblogs.com/lanlan999/p/10211280.html
Copyright © 2011-2022 走看看