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

    一、线程&进程

    对于操作系统来说,一个任务就是一个进程(Process),比如打开一个浏览器就是启动一个浏览器进程,打开一个记事本就启动了一个记事本进程,打开两个记事本就启动了两个记事本进程,打开一个Word就启动了一个Word进程。进程是很多资源的集合。

    有些进程还不止同时干一件事,比如Word,它可以同时进行打字、拼写检查、打印等事情。在一个进程内部,要同时干多件事,就需要同时运行多个“子任务”,我们把进程内的这些“子任务”称为线程(Thread)。

    由于每个进程至少要干一件事,所以,一个进程至少有一个线程。当然,像Word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之间快速切换,让每个线程都短暂地交替运行,看起来就像同时执行一样。当然,真正地同时执行多线程需要多核CPU才可能实现。线程是最小的执行单元,而进程由至少一个线程组成。

    我们在做事情的时候,一个人做是比较慢的,如果多个人一起来做的话,就比较快了,程序也是一样的,我们想运行的速度快一点的话,就得使用多进程,或者多线程,在python里面,多线程被很多人诟病,为什么呢,因为Python的解释器使用了GIL的一个叫全局解释器锁,它不能利用多核CPU,只能运行在一个cpu上面,但是你在运行程序的时候,看起来好像还是在一起运行的,是因为操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。这个叫做上下文切换。

    二、多线程,python中的多线程使用theading模块

    下面是一个简单多线程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    import threading
    import time
    def sayhi(num): #定义每个线程要运行的函数
      
        print("running on number:%s" %num)
      
        time.sleep(3)
      
    if __name__ == '__main__':
        t1 = threading.Thread(target=sayhi,args=(1,)) #生成一个线程实例
        t2 = threading.Thread(target=sayhi,args=(2,)) #生成另一个线程实例
        t1.start() #启动线程
        t2.start() #启动另一个线程

    下面是另一种启动多线程的方式,继承式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    import threading
    import time
    class MyThread(threading.Thread):
        def __init__(self,num):
            threading.Thread.__init__(self)
            self.num = num
      
        def run(self):#定义每个线程要运行的函数
      
            print("running on number:%s" %self.num)
     
            time.sleep(3)
      
    if __name__ == '__main__':
      
        t1 = MyThread(1)
        t2 = MyThread(2)
        t1.start()
        t2.start()

    这两种方式没有什么区别,两种写法而已,我个人喜欢用第一种,更简单一些。

    线程等待,多线程在运行的时候,每个线程都是独立运行的,不受其他的线程干扰,如果想在哪个线程运行完之后,再做其他操作的话,就得等待它完成,那怎么等待呢,使用join,等待线程结束

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    import threading
    import time
    def run():
        print('qqq')
        time.sleep(1)
        print('done!')
    lis = []
    for i in range(5):
        t = threading.Thread(target=run)
        lis.append(t)
        t.start()
    for t in lis:
        t.join()
    print('over')

    守护线程,什么是守护线程呢,就相当于你是一个国王(非守护线程),然后你有很多仆人(守护线程),这些仆人都是为你服务的,一但你死了,那么你的仆人都给你陪葬。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    import threading
    import time
    def run():
        print('qqq')
        time.sleep(1)
        print('done!')
    for i in range(5):
        t = threading.Thread(target=run)
        t.setDaemon(True)
        t.start()
    print('over')

    线程锁,线程锁就是,很多线程一起在操作一个数据的时候,可能会有问题,就要把这个数据加个锁,同一时间只能有一个线程操作这个数据。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    import threading
    from threading import Lock
    num = 0
    lock = Lock()#申请一把锁
    def run():
        global num
        lock.acquire()#加锁
        num+=1
        lock.release()#解锁
     
    lis = []
    for i in range(5):
        t = threading.Thread(target=run)
        t.start()
        lis.append(t)
    for t in lis:
        t.join()
    print('over',num)

    下面来个简单的爬虫,看下多线程的效果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import threading
    import requests,time
    urls  ={
        "baidu":'http://www.baidu.com',
        "blog":'http://www.nnzhp.cn',
        "besttest":'http://www.besttest.cn',
        "taobao":"http://www.taobao.com",
        "jd":"http://www.jd.com",
    }
    def run(name,url):
        res = requests.get(url)
        with open(name+'.html','w',encoding=res.encoding) as fw:
            fw.write(res.text)
     
     
    start_time = time.time()
    lis = []
    for url in urls:
        t = threading.Thread(target=run,args=(url,urls[url]))
        t.start()
        lis.append(t)
    for t in lis:
        t.join()
    end_time = time.time()
    print('run time is %s'%(end_time-start_time))
     
    #下面是单线程的执行时间
    # start_time = time.time()
    # for url in urls:
    #     run(url,urls[url])
    # end_time = time.time()
    # print('run time is %s'%(end_time-start_time))

    三、多进程,上面说了Python里面的多线程,是不能利用多核CPU的,如果想利用多核CPU的话,就得使用多进程,python中多进程使用multiprocessing模块。

    1
    2
    3
    4
    5
    6
    7
    8
    from multiprocessing import Process
    import time
    def f(name):
        time.sleep(2)
        print('hello', name)
    p = Process(target=f, args=('niu',))
    p.start()
    p.join()

     

      

      

      

  • 相关阅读:
    最佳买卖股票时期含冷冻期
    牛客网刷题笔记
    交换字符中的元素
    刷题总结
    牛客基础网刷题笔记
    买卖股票的最佳时机 II
    Solution -「51nod 1355」斐波那契的最小公倍数
    Solution -「51nod 1584」加权约数和
    Solution -「CF 1375G」Tree Modification
    Solution -「洛谷 P5787」「模板」二分图(线段树分治)
  • 原文地址:https://www.cnblogs.com/hongdoudou/p/12213661.html
Copyright © 2011-2022 走看看