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

    一.什么是线程?

    线程就是程序的执行线路

    相当于一条流水线,其包含了程序的具体执行步骤

    操作系统比喻为一个工厂,进程就是车间,线程就是流水线

     

    线程和进程的关系?

    进程中包含了运行该程序的所有资源

    进程是一个资源单位,线程cpu的最小执行单位

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

    一个进程可以包含多个线程

    进程包含线程而线程依赖于进程

     

    为什么使用线程?

    为了提高程序效率

    不用进程是因为进程对操作系统的资源消耗非常高

     

    线程是如何提高效率?

    多线程可以使cpu在一个进程内进行切换,从而提高cpu占用率

    多线程提高工作效率原理?

    默认情况下每个进程都有且只有一个主线进程,执行代码时如果遇到IO操作系统就会切换到其他应用程序,这就降低了当前应用程序的效率.

    如果含有多线程,cpu切换是在不同线程之间进行切换,加入只有两个线程,每个线程被切换到的几率为二分之一,如果一个的应用程序开启了子线,总共就有了三条线程,那么该应用程序被切到的几率就变成了三分之二!

     

    什么时候开启多线程?

    当程序中遇到IO的时候

     

    如何使用?

    两种开启线程的方式

    ①实例化Thread类

    from threading import Thread
    def task():
        print('你好!')
    t = Thread(target=task)
    t.start()
    print('over')
    

    ②继承Thread类覆盖run方法

    from threading import Thread
    class Mythread(Thread):
        def run(self):
            print('你好!')
    t = Mythread()
    t.start()
    print('over')
    

     

    进程和线程的区别?

    ①进程对操作系统的资源消耗非常高,而线程非常低(比进程低10-100倍)

    #100个进程时间统计
    from multiprocessing import Process
    import time
    def task():
      pass
    if __name__ == '__main__':
      start_time = 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_time)
    结果:6.828858137130737

    #100个线程时间统计
    from threading import Thread
    import time
    def task():
      pass
    start_time = time.time()
    ts = []
    for i in range(100):
      t = Thread(target=task)
      t.start()
      ts.append(t)
    for t in ts:
      t.join()
    print(time.time()-start_time)
    结果:0.01562190055847168

     ②在同一个进程多个线程之间资源是共享的

    from threading import Thread
    a = 0
    def task():
        print('run....')
        global a
        a = 100
    t = Thread(target=task)
    t.start()
    t.join()
    print(a)
    print('over')
    结果:
    run....
    100
    over
    

    二.守护线程

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

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

    from threading import Thread
    import time
    def task():
        print('子线程开始!')
        time.sleep(1)
        print('子线程结束!')
    t = Thread(target=task)
    #t.daemon = True
    t.setDaemon(True)
    t.start()
    print('over')
    #结果:
    子线程开始!
    over
    

    三.线程中常用的属性

    from threading import Thread
    import os
    def task():
        print('running')
        print(os.getpid())
    t1 = Thread(target=task)
    t1.start()
    t2 = Thread(target=task)
    t2.start()
    结果:
    running
    1056
    running
    1056
    在不同线程中获取到的进程ID是相同的
    
    from threading import Thread
    def task():
        print('running')
    t1 = Thread(target=task)
    t1.start()
    print(t1.is_alive())
    print(t1.isAlive())
    结果:True True 这两个是一样的
    
    from threading import Thread,current_thread,enumerate,active_count
    def task():
        print('running')
        print(current_thread()) #获取当前线程对象
        print(active_count()) #当前正在运行的线程数量 结果:2
    t1 = Thread(target=task)
    t1.start()
    print(t1.getName()) #获取该线程的名字
    print(enumerate()) #获取所有线程对象
    print(active_count()) #当前正在运行的线程数量 结果:1
    

    四.线程互斥锁

    什么时候用锁?

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

    from threading import Thread,Lock
    import time
    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 Thread,Semaphore,current_thread
    import time
    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()
    

    进程中 队列守护进程的应用 生产者消费者模型 :思聪吃热狗

    from multiprocessing import Process,JoinableQueue
    import time,random
    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)
    def eat_hotdog(name,q):
        while True:
            res = q.get()
            print('%s吃了%s'%(name,res))
            time.sleep(random.randint(1,2))
            q.task_done() #记录已经被处理的数据的数量
    if __name__ == '__main__':
        q = JoinableQueue()
        #生产者1
        m1 = Process(target=make_hotdog,args=('万达热狗店',q))
        m1.start()
        #生产者2
        m2 = Process(target=make_hotdog,args=('京东热狗店',q))
        m2.start()
        #消费者
        e = Process(target=eat_hotdog,args=('思聪',q))
        e.daemon = True  #设置消费者为守护进程
        e.start()
        #保证生产者全部生产完成
        m1.join()
        m2.join()
    
        #保证队列中的数据全部被处理了
        q.join() #明确生产方已经不会再产生数据了
    

      

  • 相关阅读:
    css引入方式
    HTML标签
    动态导入模块impoerlib
    pymysql连接数据库
    创建数据库表之引擎
    IO多路复用互动聊天,select函数监听
    欧拉筛法求素数个数
    与三角形相关的问题 WITH 有向面积
    时间复杂度的计算
    折半查找
  • 原文地址:https://www.cnblogs.com/lizeqian1994/p/10210446.html
Copyright © 2011-2022 走看看