线程:是进程中一个“单一连续的控制流”、执行路径
- 线程又被称为轻量级进程
- 一个进程可拥有多个并行的线程
- 一个进程中的线程共享相同的内存单元、内存地址空间,可以访问相同的变量和对象,而且他们从同一堆中分配对象,通信、数据交换、同步操作,缺点线程是对全局变量随意修改,可能造成多线程之间对全局变量的混乱(不安全),可以通过传参的方式调用全局变量(不适用可变类型),但是修改次数过多,会有多次线程切换,产生紊乱
-
import threading,time g_num = 100 def worker1(): global g_num for i in range(3): g_num +=1 print("in worker1,g_nun=%s"%g_num) def worker2(): print("in worker2,g_nun=%s" % g_num) w1 = threading.Thread(target=worker1) w1.start() time.sleep(1) w2 = threading.Thread(target=worker2) w2.start()
通过传参的方式调用局部变量:
import threading,time g_num = 100 def worker1(num): for i in range(3): num +=1 print("in worker1,g_nun=%s"%num) def worker2(num): print("in worker2,g_nun=%s" % num) w1 = threading.Thread(target=worker1,args=(g_num,)) w1.start() time.sleep(1) w2 = threading.Thread(target=worker2,args=(g_num,)) w2.start()
给线程加锁 ,有时锁过多会出现死锁的问题。
import threading,time g_num = 100 def worker1(num): for i in range(300000): mutexFlag = mutex.acquire(True) if mutexFlag: num +=1 mutex.release() print("in worker1,g_nun=%s" % num) def worker2(num): print("in worker2,g_nun=%s" % num) mutex = threading.Lock() w1 = threading.Thread(target=worker1,args=(g_num,)) w1.start()
给线程加锁,实现线程按顺序执行
-
from threading import Thread,Lock from time import sleep class Task1(Thread): def run(self): while True: if lock1.acquire(): print("--Task1--") sleep(0.5) lock2.release() class Task2(Thread): def run(self): while True: if lock2.acquire(): print("--Task2--") sleep(0.5) lock3.release() class Task3(Thread): def run(self): while True: if lock3.acquire(): print("--Task3--") sleep(0.5) lock1.release() lock1 = Lock() lock2 = Lock() lock2.acquire() lock3 = Lock() lock3.acquire() t1 = Task1() t2 = Task2() t3 = Task3() t1.start() t2.start() t3.start()
- 由于线程间的通信是在同一地址空间上进行的,所以不需要额外的通信机制,这就使得通信更简单而且信息传递的速度也更快
- 有三种状态,就绪,阻塞,运行
线程和进程的区别
- 进程是系统进行资源分配和调度的一个独立单位(资源分配)
- 进程在执行过程中拥有独立的内存单元,多个线程共享内存,从而极大的提高了程序的运行效率
- 一个程序至少有一个进程,一个进程至少有一个线程
- 线程是进程的一个实体,CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位(调度执行)
- 线程自己基本不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程贡献进程所有的全部资源
- 线程的划分尺度小于进程(资源比进程少),使得多线程程序的并发性高
- 线程不能独立运行,必须依存在进程中
- 线程和进程在使用时各有优缺点,线程执行开销小,但不利于资源的管理和保护,而进程则相反。
线程的数量
-
import threading import time def saySorry(): for i in range(1, 5): print("I'm sorry*") time.sleep(1) def getOut(): for i in range(1, 5): print("get out of my sight*") time.sleep(2) if __name__ == "__main__": t1 = threading.Thread(target=saySorry) t2 = threading.Thread(target=getOut) t1.start()#启动线程 t2.start()#启动线程 while True: length = len(threading.enumerate()) print("当前的线程数量:%s"%length) if length <= 1: break time.sleep(0.5)
线程子类化,改写run() ,如果要传参,则改写__init__方法
-
import threading import time class MyThread(threading.Thread): def run(self): for i in range(3): time.sleep(1) msg = "I am "+self.name+"@"+str(i) print(msg) if __name__ == "__main__": t = MyThread() t.start()
queue实现线程按照顺序执行
-
from threading import Thread #Python3 from queue import Queue from time import sleep class Produce(Thread): def run(self): global queue count = 0 while True: if queue.qsize()<1000: for i in range(100): count = count + 1 msg =self.name + "生成产品" + str(count) queue.put(msg) print(msg) sleep(0.5) class Consumer(Thread): def run(self): global queue while True: if queue.qsize()>100: for i in range(3): msg = self.name + "消费了" + queue.get() print(msg) sleep(1) queue = Queue() for i in range(500): queue.put("初始产品"+str(i)) for i in range(2): p = Produce() p.start() for i in range(5): c= Consumer() c.start()
ThreadLocal变量
一个ThreadLocal变量虽然是全局变量,但是每个线程都只能读写自己线程的独立副本,互不干扰,ThreadLocal结局了参数在一个线程中各个函数之间相互传递的问题,可以理解ThreadLocal是一个dict,可以绑定其他变量。ThreadLocal最常用到的地方是为每个线程绑定一个数据库链接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数,都可以非常方便的访问这些资源
-
import threading #创建ThreLocal localschool = threading.local() def processStudent(): name = localschool.student print("hello!%s in %s"%(name,threading.current_thread().name)) def processThread(name): localschool.student = name processStudent() t1 = threading.Thread(target=processThread,args=("zs",),name="t1") t2 = threading.Thread(target=processThread,args=("ww",),name="t2") t1.start() t2.start() t1.join() t2.join()