zoukankan      html  css  js  c++  java
  • python从入门到放弃之线程篇

    ,什么是多线程?

    1.多线程的概念?

      说起多线程,那么就不得不说什么是线程,而说起线程,又不得不说什么是进程。

      进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。在早期面向进程设计的计算机结构中,进程是程序的基本执行实体;在当代面向线程设计的计算机结构中,进程是线程的容器。程序是指令、数据及其组织形式的描述,进程是程序的实体。

      以上是百度百科对进程的解释。

      进程可以简单的理解为一个可以独立运行的程序单位。它是线程的集合,进程就是有一个或多个线程构成的,每一个线程都是进程中的一条执行路径。

      那么多线程就很容易理解:多线程就是指一个进程中同时有多个执行路径(线程)正在执行。

      为什么要是用多线程?

      1.在一个程序中,有很多的操作是非常耗时的,如数据库读写操作,IO操作等,如果使用单线程,那么程序就必须等待这些操作执行完成之后才能执行其他操作。使用多线程,可以在将耗时任务放在后台继续执行的同时,同时执行其他操作。

      2.可以提高程序的效率。

      3.在一些等待的任务上,如用户输入,文件读取等,多线程就非常有用了。

      缺点:

      1.使用太多线程,是很耗系统资源,因为线程需要开辟内存。更多线程需要更多内存。

      2.影响系统性能,因为操作系统需要在线程之间来回切换。

      3.需要考虑线程操作对程序的影响,如线程挂起,中止等操作对程序的影响。

      4.线程使用不当会发生很多问题。

      总结:多线程是异步的,但这不代表多线程真的是几个线程是在同时进行,实际上是系统不断地在各个线程之间来回的切换(因为系统切换的速度非常的快,所以给我们在同时运行的错觉)。

    2.多线程与高并发的联系。

      高并发:高并发指的是是一种系统运行过程中遇到的一种“短时间内遇到大量操作请求”的情况,主要发生在web系统集中大量访问或者socket端口集中性收到大量请求(例如:12306的抢票情况;天猫双十一活动)。该情况的发生会导致系统在这段时间内执行大量操作,例如对资源的请求,数据库的操作等。如果高并发处理不好,不仅仅降低了用户的体验度(请求响应时间过长),同时可能导致系统宕机,严重的甚至导致OOM异常,系统停止工作等。如果要想系统能够适应高并发状态,则需要从各个方面进行系统优化,包括,硬件、网络、系统架构、开发语言的选取、数据结构的运用、算法优化、数据库优化……。

      而多线程只是在同/异步角度上解决高并发问题的其中的一个方法手段,是在同一时刻利用计算机闲置资源的一种方式。

      多线程在高并发问题中的作用就是充分利用计算机资源,使计算机的资源在每一时刻都能达到最大的利用率,不至于浪费计算机资源使其闲置。

     

    3.线程的创建

      首先引入包

        from threading import Thread

      然后实力化一个对象

        t = Thread(target=func,args=(i,))

      启动一个子线程线程
        t.start()

    主线程默认等待所有子线程执行完毕结束运行

     (1) 进程中可以包含多个线程

    1 def func(num):
    2     time.sleep(random.uniform(0.1,1))
    3     print("子线程" , num , os.getpid())
    4     
    5 for i in range(10):
    6     t = Thread(target=func,args=(i,))
    7     t.start()

    (2) 并发多线程 和 多进程,谁的速度快 => 多线程

     1 def func(num):
     2     print("子线程" , num , os.getpid())
     3 
     4 if __name__ == "__main__":
     5     startime = time.perf_counter()
     6     lst = []
     7     
     8     for i in range(1000):
     9         t = Thread(target=func,args=(i,))
    10         t.start()
    11         lst.append(t)
    12         
    13     for i in lst:
    14         # print(i)
    15         i.join()
    16         
    17     endtime = time.perf_counter()
    18     print("多线程执行的时间:",endtime-startime)# 0.1063898997406085
    19 
    20 
    21     # 多进程的执行时间
    22     startime = time.perf_counter()
    23     lst = []
    24     for i in range(1000):
    25         p = Process(target=func,args=(i,))
    26         p.start()
    27         lst.append(p)
    28     
    29     for i in lst:
    30         i.join()        
    31     endtime = time.perf_counter()
    32     print("多进程执行的时间:",endtime-startime) # 多进程执行的时间: 19.968611914504738

     

    (3) 多线程共享同一份进程资源 

      """线程和线程之间是异步并发的"""

     1 num = 1000
     2 lst = []
     3 def func():
     4     # 异步并发程序
     5     # time.sleep(1000)
     6     global num
     7     num -= 1
     8     
     9     
    10 for i in range(1000):
    11     t = Thread(target=func)
    12     t.start()
    13     lst.append(t)
    14     
    15 for i in lst:
    16     i.join()
    17     
    18 print(num)

     

    (4) 线程相关的函数

     

    线程.is_alive() 检测线程是否仍然存在
    线程.setName() 设置线程名字
    线程.getName() 获取线程名字

    from threading import Thread,current_thread,currentThread

    1.currentThread().ident 查看线程id号
    2.enumerate() 返回目前正在运行的线程列表
    3.activeCount() 返回目前正在运行的线程数量

     

    检测当前线程的名字

     1 def func():
     2     # pass
     3     time.sleep(0.5)
     4     
     5 t = Thread(target=func)
     6 print(t)
     7 t.start()
     8 print(t.is_alive())
     9 print(t.getName())
    10 t.setName("producer_wangwen1号")#设置当前线程的名字
    11 print(t.getName())
    # 1.currentThread().ident 查看线程id号 
    1 from threading import currentThread
    2 def func():
    3     print("子线程:",currentThread().ident)
    4 
    5 t = Thread(target=func)
    6 t.start()
    7 print("主线程:",currentThread().ident)

     

      2.enumerate()        返回目前正在运行的线程列表

     1 from threading import enumerate
     2 from threading import currentThread
     3 import time
     4 from threading import Thread,current_thread,currentThread
     5 def func():
     6     print("子线程:", currentThread().ident)
     7     time.sleep(0.5)
     8 
     9 
    10 for i in range(10):
    11     t = Thread(target=func)
    12     t.start()
    13 
    14 print(enumerate())
    15 print(len(enumerate()))

     

     

     1 # 3.activeCount() 返回目前正在运行的线程数量 (了解)
     2 from threading import activeCount
     3 from threading import currentThread
     4 def func():
     5 print("子线程:",currentThread().ident)
     6 time.sleep(0.5)
     7 for i in range(10):
     8 t = Thread(target=func)
     9 t.start()
    10 
    11 print(activeCount())
    12 
    13  

    # ### 守护线程: 等待所有线程全部执行结束之后,在终止,守护所有线程;
    """主线程默认等待所有的子线程;""" 

     

    
    
     1 from threading import Thread
     2 import time
     3 def func1():
     4     while True:
     5         time.sleep(0.5)
     6         print("我是子线程func函数")
     7 
     8 def func2():
     9     print("func2 start ...")
    10     time.sleep(3)
    11     print("func2 end ... ")
    12 
    13 t1 = Thread(target=func1)
    14 # 设置守护线程,在start调用之前进行设置 setDaemon
    15 t1.setDaemon(True)
    16 t1.start()
    17 
    18 t2 = Thread(target=func2)
    19 t2.start()
    20 
    21 print("我是主线程 ... ")
    
    
    
    
    

     # ### lock 线程锁,用来保证线程数据安全与进程锁同理,一旦使用异步程序会变为同步,一般用于抢票

     1 from threading import Thread,Lock
     2 n = 0
     3 def func1(lock):
     4     global n
     5     
     6     for i in range(1000000):
     7         lock.acquire()
     8         # 写法一        
     9         n -= 1
    10         lock.release()
    11     
    12 def func2(lock):
    13     global n
    14     for i in range(1000000):
    15         # 写法二
    16         with lock:
    17             n += 1
    18 
    19 if __name__ == "__main__":
    20     # 创建一把锁
    21     lock = Lock()
    22     lst = []
    23     for i in range(10):
    24         # 10个线程专门负责加1
    25         t1 = Thread(target=func1,args=(lock,))
    26         # 10个线程专门负责减1
    27         t2 = Thread(target=func2,args=(lock,))
    28         t1.start()
    29         t2.start()
    30         lst.append(t1)
    31         lst.append(t2)
    32     
    33     for i in lst:
    34         i.join()
    35         
    36     print("主线程执行结束 ... ")
    37     print(n)

     # ### 信号量 Semaphore

      同时上多把锁,与进程锁原理是一样的

     1 from threading import Semaphore,Thread
     2 import time
     3 def func(i,sem):
     4     with sem:
     5         print(i)
     6         time.sleep(10)
     7         
     8 
     9 sem = Semaphore(6)
    10 for i in range(20):
    11     Thread(target=func,args=(i,sem)).start()
  • 相关阅读:
    jstl标签的fmt:formatDate格式化日期 String to Date
    Spring MVC使用ModelAndView进行重定向
    配置SpringAop时需要用到的AspectJ表达式
    深入分析Java Web中的编码问题
    第六十五条:不要忽略异常
    第六十四条:努力使失败保持原子性
    第六十三条:在细节消息中包含能捕获失败的信息
    第六十二条:每个方法抛出的异常都要有文档
    第六十一条:抛出与抽象相对应的异常
    第六十条:优先使用标准的异常
  • 原文地址:https://www.cnblogs.com/zyling/p/11930351.html
Copyright © 2011-2022 走看看