• Python学习 :多线程


     多线程

      什么是线程?

      - 能独立运行的基本单位——线程(Threads)。

      - 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。

      - 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

      - 就好比生产的工厂,一个车间的工作过程是一个进程,车间中的一条条流水线工作的过程是不同的线程。

      下面的图片就是线程与进程之间的关系

     

      注意:进程是资源分配的最小单位,线程是CPU调度的最小单位.

                 每一个进程中至少有一个线程。

      线程与进程的区别可以归纳为以下4点:

      1)地址空间和其它资源(如打开文件):进程间的地址空间相互独立,同一进程的各线程间共享进程的地址空间。某进程内的线程在其它进程不可见

      2)通信:进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性

      3)调度和切换:线程上下文切换比进程上下文切换要快得多

      4)在多线程操作系统中,进程不是一个可执行的实体

      创建多线程简例

    import time
    import threading
    
    def foo(n):
        print('线程%s'%n)
        time.sleep(3)
        print('线程%s结束' % n)
    
    def bar(n):
        print('线程%s' % n)
        time.sleep(2)
        print('线程%s结束' % n)
    
    begin = time.time()
    print('------------主线程------------')
    # 创建线程对象
    t1 = threading.Thread(target = foo,args = (1,))
    t2 = threading.Thread(target = bar,args = (2,))
    # 通过 os 调度来抢占 cpu资源
    
    t1.start()
    t2.start()
    
    # 线程不结束就不会继续向下进行
    t1.join()
    t2.join()
    
    end = time.time()
    print(end-begin)
    

      join()方法

      - join()方法会使线程在join处进行阻塞,倘若线程没完成就不会继续向下运行

    import time
    import threading
    from time import ctime,sleep
    
    def music(func):
        for i in range(2):
            print ("Begin listening to %s. %s" %(func,ctime()))
            sleep(4)
            print("----------end listening %s----------"%ctime())
    
    def moive(func):
        for i in range(2):
            print ("Begin watching at the %s! %s" %(func,ctime()))
            sleep(5)
            print('----------end watching %s----------'%ctime())
    
    threads = []
    t1 = threading.Thread(target=music,args=('晴天',))
    threads.append(t1)
    t2 = threading.Thread(target=moive,args=('肖申克的救赎',))
    threads.append(t2)
    
    if __name__ == '__main__':
        start = time.time()
        for t in threads:
            t.start()
            #t.join() # t 先取的值为 t1 ,t1不结束就不会继续向下走,此时相当于串行
            #t1.join() # 与 t.join() 效果一致
        t.join() # 在python中不会报错,此时取值为 t2
        #t2.join()  # 在 t2 运行完成后,才会完成后续代码
        print ("all over %s" %ctime())
        end = time.time()
        print(end - start)
    

      守护线程 Daemon

      - 守护线程setDaemon(True),必须在start() 方法调用之前设置,否则将会报错

      - 如果不设置为守护线程程序会被无限挂起。这个方法基本和join是相反的。

      - 主线程一旦结束,子线程也同时结束

      - 当主线程完成时不需要某个子线程完全运行完就要退出程序,那么就可以将这个子线程设置为守护线程,

    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(10)
    
    if __name__ == '__main__':
        begin = time.time()
        t1 = MyThread(1)
        t2 = MyThread(2)
        threads = [t1, t2]
        for t in threads:
            t.setDaemon(True)
            t.start()
        print('进程结束!')
        end = time.time()
        print(end-begin)
    

      队列 queue

      - queue类的方法

    创建一个“队列”对象
    import Queue
    q = Queue.Queue(maxsize = 10)
    Queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。
    
    将一个值放入队列中
    q.put(10)
    调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为
    1。如果队列当前为空且block为1,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为0,put方法将引发Full异常。
    
    将一个值从队列中取出
    q.get()
    调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False,队列将引发Empty异常。
    
    Python Queue模块有三种队列及构造函数:
    1、Python Queue模块的FIFO队列先进先出。  class queue.Queue(maxsize)
    2、LIFO类似于堆,即先进后出。             class queue.LifoQueue(maxsize)
    3、还有一种是优先级队列级别越低越先出来。   class queue.PriorityQueue(maxsize)
    
    此包中的常用方法(q = Queue.Queue()):
    q.qsize() 返回队列的大小
    q.empty() 如果队列为空,返回True,反之False
    q.full() 如果队列满了,返回True,反之False
    q.full 与 maxsize 大小对应
    q.get([block[, timeout]]) 获取队列,timeout等待时间
    q.get_nowait() 相当q.get(False)
    非阻塞 q.put(item) 写入队列,timeout等待时间
    q.put_nowait(item) 相当q.put(item, False)
    q.task_done() 在完成一项工作之后,q.task_done() 函数向任务已经完成的队列发送一个信号
    q.join() 实际上意味着等到队列为空,再执行别的操作
    

      队列的简例

    import threading,queue
    from time import sleep
    from random import randint
    class Production(threading.Thread):
        def run(self):
            while True:
                r = randint(0,100)
                q.put(r)
                print("生产出来%s号包子"%r)
                sleep(1)
    class Proces(threading.Thread):
        def run(self):
            while True:
                re = q.get()
                print("吃掉%s号包子"%re)
    if __name__=="__main__":
        q = queue.Queue(10)
        threads = [Production(),Production(),Production(),Proces()]
        for t in threads:
            t.start()
    
  • 相关阅读:
    GPS文件处理
    ArcEngine整个Map选择集的闪烁以及跨图层选择集导出为Shp
    查询和“1002”号的同学学习的课程完全相同的其他同学学号和姓名
    GPS文件处理(后续)——计算单词数
    辩者二十一事
    ArcEngine添加栅格后,不能闪烁问题
    struts2 模型驱动的action赋值优先顺序
    easyui placeholder 解决方案
    velocity的foreach下标
    javascript动态改变iframe的src
  • 原文地址:https://www.cnblogs.com/ArticleYeung/p/10657958.html
Copyright © 2020-2023  润新知