定义
1.线程:是进程中一个"单一的连续控制流程"/执行路径
2.线程又被称为轻量级进程(lightweight process)
3.Threads run at the sama time,independently of one another
4.一个进程可拥有多个并行的线程(concurrent).
●进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。
●一个程序至少有一个进程,一个进程至少有一个线程
●线程是进程的一个实体,是CPU调度和分派的基本单位,他是比进程更小的能独立运行的基本单位。
●线程是自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(计数程序,一组寄存器和栈),但是他可与同属一个进程的其他线程共享进程所拥有的全部资源。
●线程的划分尺度小于进程(资源比进程小),使得多线程程序的并发性高
●线程不能独立执行,必须依存在进程中
●线程和进程在使用上各有优缺点:线程执行开销小,但是不利于资源的管理和保护,进程反之
在一个进程内的所有线程共享全局变量,能够在不适用其他方式的前提下完成多线程之间的数据共享
缺点就是,线程是对全局变量随意遂改可能造成多线程之间全局变量的混乱(线程非安全)
Threading模块常用方法
threading.activeCount(): 返回正在运行的线程数量。
threading.currentThread(): 返回当前的线程变量。
threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
len(threading.enumerate)==threading.activeCount结果是True
线程模块同样提供了Thread类来处理线程,Thread类提供了以下方法:
run(): 用以表示线程活动的方法。
start():开启线程。
join([time]): 设置join之后,主线程等待子线程全部执行完成后
或者子线程超时后,主线程才结束。
isAlive(): 返回线程是否活动的。
getName(): 返回线程名。
setName(): 设置线程名。
例子:
import threading
from time import sleep,ctime
def sing():
for i in range(3):
print("正在唱歌...%d"%i)
sleep(1)
def dance():
for i in range(3):
print("正在跳舞...%d"%i)
sleep(1)
if __name__ == "__main__":
print("----开始----%s"%ctime())
t1=threading.Thread(target=sing)
t1.start()
t2=threading.Thread(target=dance)
t2.start()
while True:
#查看进程次数
length = len(threading.enumerate())
# length=threading.active_count()
print("当前运行的线程数为:%d"%length)
if length <= 1:
break
sleep(0.5)
例二:
import threading
from time import time,sleep
def fun(num):
print("线程执行%d"%num)
sleep(2)
for i in range(5):
#简单的线程
t=threading.Thread(target=fun,args=(i+1,))
t.start()
print("\n主线程结束")
print(threading.active_count())
例三:
#重写run方法
import threading
import time
class MyThread(threading.Thread):
def __init__(self,num,str1):
super().__init__()
self.num=num
self.str1=str1
def run(self):
for i in range(3):
time.sleep(1)
msg="I'm "+self.name+'@'+str(i)+" num :"+str(self.num)+"str1:"+self.str1
print(msg)
if __name__=="__main__":
t=MyThread(10,'abc')
t.start()
例四:
import threading
import time
g_num = 0
def work1(num):
global g_num
for i in range(num):
g_num += 1
print("----in work1, g_num is %d---" % g_num)
def work2(num):
global g_num
for i in range(num):
g_num += 1
print("----in work2, g_num is %d---" % g_num)
print("---线程创建之前g_num is %d---" % g_num)
t1 = threading.Thread(target=work1, args=(1000000,)) # 改为1000000
t1.start()
t2 = threading.Thread(target=work2, args=(1000000,)) # 改为1000000
t2.start()
while len(threading.enumerate()) != 1:
time.sleep(1)
print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
例五:
#锁
import threading
import time
g_num=0
def work1(num):
global g_num
mexFlag=mex.acquire(True)#加锁
if mexFlag:
for i in range(num):
g_num+=1
mex.release()
print("work1------%d-------" % g_num)
def work2(num):
global g_num
mexFlag = mex.acquire(True) # 加锁
if mexFlag:
for i in range(num):
g_num+=1
mex.release()
print("\nwork2------%d-------"%g_num)
if __name__=="__main__":
mex=threading.Lock()#互斥锁
t=threading.Thread(target=work1,args=(1000000,))
t.start()
t1=threading.Thread(target=work2,args=(1000000,))
t1.start()
while True:
if len(threading.enumerate()) !=1:
time.sleep(1)
else:
break;
print("2个线程对同一个全局变量操作之后的最终结果是:%s" % g_num)
#
# import threading, multiprocessing
# def loop():
# x = 0
# while True:
# x = x ^ 1
# for i in range(multiprocessing.cpu_count()*2):
# t = threading.Thread(target=loop)
# t.start()
# print(multiprocessing.cpu_count())
一把锁如果忘了解锁会形成死锁,多吧锁也可能形成死锁
多把锁形成死锁
使用锁使程序顺序运行
通知锁控制线程的执行顺序
from threading import Thread,Lock
import time
class Thread1(Thread):
def run(self):
while True:
if lock1.acquire():
print("lock1------")
time.sleep(2)
lock2.release()
class Thread2(Thread):
def run(self):
while True:
if lock2.acquire():
print("lock2------")
time.sleep(2)
lock3.release()
class Thread3(Thread):
def run(self):
while True:
if lock3.acquire():
print("lock3------")
time.sleep(2)
lock1.release()
if __name__=="__main__":
#使用Lock()创建互斥锁
lock1=Lock()
lock2=Lock()
# 锁上
lock2.acquire()
lock3=Lock()
# 锁上
lock3.acquire()
t1=Thread1()
t2=Thread2()
t3=Thread3()
t1.start()
t2.start()
t3.start()
#不加锁的情况
# #通知锁控制线程的执行顺序
# from threading import Thread,Lock
# import time
# class Thread1(Thread):
# def run(self):
# while True:
#
# print("lock1------")
# time.sleep(1)
#
# class Thread2(Thread):
# def run(self):
# while True:
#
# print("lock2------")
# time.sleep(1)
#
# class Thread3(Thread):
# def run(self):
# while True:
#
# print("lock3------")
# time.sleep(1)
#
# if __name__=="__main__":
#
# t1=Thread1()
# t2=Thread2()
# t3=Thread3()
# t1.start()
# t2.start()
# t3.start()
如何去在线程的执行过程中销毁对象
import time
import threading
class DownThread:
def __init__(self):
self._running = True
def terminate(self):
self._running = False
def run(self, n):
while self._running and n > 0:
print('T-minus', n)
n -= 1
time.sleep(1)
if __name__ == '__main__':
c = DownThread()
t = threading.Thread(target=c.run, args=(10,))
t.start()
time.sleep(3)
c.terminate()
t.join()
ThreadLocal变量
#ThreadLocal变量
import threading
#创建全局ThreadLocal对象
local_school=threading.local()
def process_student():
#获取当前关联的student:
std=local_school.student
print("Hello,%s(in %s)"%(std,threading.currentThread().name))
def process_thread(name):
#绑定上面函数的student
local_school.student=name
process_student()
t1=threading.Thread(target=process_thread,args=("zhangsan",),name="t1")
t2 =threading.Thread(target=process_thread,args=("老王",),name="t2")
t1.start()
t2.start()
t1.join()
t2.join()
线程池
# 一个线程的运行时间可以分为3部分:线程的启动时间、线程体的运行时间和线程的销毁时间。
# 在多线程处理的情景中,如果线程不能被重用,就意味着每次创建都需要经过启动、销毁和运行3个过程。
# 这必然会增加系统相应的时间,降低了效率。
# 使用线程池:由于线程预先被创建并放入线程池中,同时处理完当前任务之后并不销毁而是被安排处理下一个任务,
# 因此能够避免多次创建线程,从而节省线程创建和销毁的开销,能带来更好的性能和系统稳定性。
# 线程池基本原理: 我们把任务放进队列中去,然后开N个线程,每个线程都去队列中取一个任务,
# 执行完了之后告诉系统说我执行完了,然后接着去队列中取下一个任务,直至队列中所有任务取空,退出线程。
import threading
from threading import Thread
import time
from queue import Queue
# 创建队列实例, 用于存储任务
queue = Queue()
# 定义需要线程池执行的任务
def do_job():
while True:
i = queue.get()
time.sleep(1)
print('index %s, curent: %s' % (i, threading.current_thread()))
queue.task_done()
if __name__ == '__main__':
# 创建包括3个线程的线程池
for i in range(3):
t = Thread(target=do_job)
t.start()
# 模拟创建线程池3秒后塞进10个任务到队列
time.sleep(3)
for i in range(10):
queue.put(i)
queue.join()