python 多线程与队列

  • 概念
    • 以抛异常的形式实现,达到线程结束的目的
  • 线程基础
    • 使用线程可以把占据长时间的程序中的任务放到后台去处理
    • 每个独立的进程有一个程序运行的入口,顺序执行序列和程序的出口
    • 线程不能独立运行,必须依存在应用程序中,由应用程序提供多个线程执行控制
    • 线程的结束
      • 一般依靠线程函数的自然结束
      • 也可以在线程函数中调用thread.exit(),抛出SystemExit exception,达到退出线程的目的
  • 线程模块
    • thread 标准库 提供低级别,原始线程及简单锁
    • threading 标准库, 其提供以下方法
      • threading.currentThread() 返回当前线程变量
      • threading.enumerate() 返回一个包含正在运行的线程list
      • threading.activdCount() 返回正在运行的线程数量
    • threading.Thread类来处理线程,有以下方法
      • run()
      • start()
      • join([time]) 阻塞调用线程
        • 等待至线程中止
        • 阻塞调用线程直到线程的join()方法被调用中止,正常退出或抛出未处理的异常或是可选的超时发生
      • isAlive()
      • getAlive()
      • getName()
      • setName()
  • python 线程
    • 函数式
      • thread.start_new_thread ( function, args[, kwargs] )
        • 线程函数,tuple类型的线程函数参数,可选的关键字参数
    • 类对象的形式
      • threading.Thread
      • 同java类似,也需要启动线程,后台线程执行run方法
  • 多线程会造成线程竞争资源,会造成数据不一致
    • 线程同步
      • 原因:竞争性获取CPU资源
      • 锁的概念
        • threading.Lock, threading.Rlock 类对象
        • acquire与release方法
      • 锁的状态
        • 锁定和未锁定
        • 原理
          • 访问共享数据时,先获取锁定
          • 若有别的线程获取了锁,那么让当前线程在访问同步数据时则暂停,即同步阻塞
          • 别线程释放锁后,再访问,基本流程:访问 -> 获取锁 -> 使用共享数据 -> 释放锁 -> 访问结束
      • 线程执行流程
        • 创建线程 -> 开启线程 -> 等待系统调度
  • 线程优先级队列
    • Queue模块提供了同步的,线程安全的队列类,实现了锁原语

      • 先入先出队列Queue
      • 后入先出队列LifoQueue
      • 优先级队列 PriorityQueue
    • Queue模块常用方法

      • Queue.qsize() 返回队列的大小
      • Queue.empty() 如果队列为空,返回True,反之False
      • Queue.full() 如果队列满了,返回True,反之False
      • Queue.full 与 maxsize 大小对应
      • Queue.get([block[, timeout]])获取队列,timeout等待时间
      • Queue.get_nowait() 相当Queue.get(False)
      • Queue.put(item) 写入队列,timeout等待时间
      • Queue.put_nowait(item) 相当Queue.put(item, False)
      • Queue.task_done() 在完成一项工作之后,Queue.task_done()函数向任务已经完成的队列发送一个信号
      • Queue.join() 实际上意味着等到队列为空,再执行别的操作
    • 补充python多线程thread join() 作用

      • join方法的阻塞,等待子线程结束
      • 依次检验线程池中的线程是否结束,没有结束就阻塞直到线程结束,如果结束则跳转执行下一个线程的join函数。
      1. 阻塞主进程,专注于执行多线程中的程序。
      2. 多线程多join的情况下,依次执行各线程的join方法,前头一个结束了才能执行后面一个。
      3. 无参数,则等待到该线程结束,才开始执行下一个线程的join。
      4. 参数timeout为线程的阻塞时间,如 timeout=2 就是罩着这个线程2s 以后,就不管他了,继续执行下面的代码。

示例代码

# coding: utf-8

import Queue
import threading
import time

exitFlag = 0

class myThread(threading.Thread):
    def __init__(self, threadID,name,q):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.q = q

    def run(self):
        print "Starting " + self.name
        process_data(self.name,self.q)
        print "Exiting " + self.name


def process_data(threadName, q):
    while not exitFlag:
        queueLock.acquire()
        if not workQueue.empty():
            data = q.get()
            queueLock.release()
            print "%s processing %s" % (threadName, data)
        else:
            queueLock.release()
        time.sleep(1)
    

threadList = ["Thread-1", "Thread-2", "Thread-3"]
nameList = ["One", "Two", "Three", "Four", "Five"]
queueLock = threading.Lock()
workQueue = Queue.Queue(10)
threads = []
threadID = 1

# 创建新线程
for tName in threadList:
    thread = myThread(threadID, tName, workQueue)
    thread.start()
    threads.append(thread)
    threadID +=1

# 填充队列
queueLock.acquire()
for word in nameList:
    workQueue.put(word)
queueLock.release()

# 等待队列清空
while not workQueue.empty():
    pass

# 通知线程是时候退出
exitFlag = 1

# 等待所有线程完成
for t in threads:
    t.join()
print "Exiting Main Thread"
©️2020 CSDN 皮肤主题: 技术工厂 设计师:CSDN官方博客 返回首页