一、作者感慨
。
二、什么是线程/进程
线程是操作系统能够进行运算调度的最小单位。他被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中的一个单一顺序的控制流,一个进程中可以并发多个线程,每个线程并行执行不同的任务。
进程:要以一个整体的形式暴露给操作系统管理,里面包含对各种资源的调用,堆存的管理,网络接口调用等,对资源管理的集合就可以成为进程
线程:是操作系统最小的调度单位,是一串指令的集合
进程 要操作cpu,必须要创建一个线程~
作者大白话解释:
电脑有固定的内存,我们可以吧应用程序理解成进程,当我们打开各种各样的应用程序的时候,我们的内存就会越来越小,这是因为进程调度内存空间,不同进程占用不同的空间相互不进行干涉,可以理解成qq程序崩溃不会影响到word程序,线程在进程中,线程会跟cup进行联系调度,如果qq进程中 一个线程崩溃,会导qq进程的崩溃~简单理解进程就是划分程序要用的内存,里面包含着一些进程,进程会跟cup进行运算的调度
三、区别
如果有人问你,进程和线程那个运行快,你要注意了因为两者没有可比性,线程跟进程被包含关系,但如果问线程和进程谁启动的快,这儿时候线程快
线程:所有同一个进程里的线程是共享同一块内存空间的(上面不是说了面进程是开辟空间的,线程在进程中,所有线程当然是共享进程开辟出来的空间的)
1.线程是共享内存空间,进程的内存是独立的
2.多进程是相互独立的,多线程会产生相互干扰(进程是开辟房间互不打扰,而线程是使用进程的房间,多个线程难免不会出现相互干扰的现象)
3.一个进程的线程之间可以直接交流,两个进程想通信,必须通过一个中间代理来实现
4.创建新线程很简单,创建新进程需要对其父进程进行一次克隆
5.一个线程可以控制和操作同一进程里的其他线程,但是进程只能操作子进程
四、python多线程实例
这里需要引入一个新的模块threading,调用thread方法其中target参数函数,args是函数的参数~
例一未使用多线程
import time
def run(n):
print('task',n)
time.sleep(2)
run('t1')
run('t2')
例二 多线程
import threading
import time
def run(n):
print('task',n)
time.sleep(2)
t1 = threading.Thread(target=run,args=('t1',))
t2 = threading.Thread(target=run,args=('t2',))
t1.start()
t2.start()
其实我们可以通过类的形式写多线程
import threading
import time
class MyTreading(threading.Thread):
def __init__(self,n):
super(MyTreading,self).__init__()
self.n = n
def run(self):
print("多线程"+self.n)
t1 = MyTreading("t1")
t2 = MyTreading("t2")
t1.start()
t2.start()
主线程和子线程又是什么关系呢?
代码一
import threading
import time
list_threading = []
def run(n,m):
print("线程%s"%n)
time.sleep(m)
star_time = time.time()
for i in range(50):
t1 = threading.Thread(target=run,args=(i,i/10+0.1) )
t1.start()
print('主线程')
print(float(time.time()-star_time)
上面这个程序的运行时间为0.015604257583618164 s,那我们写一个样的程序单线程的看看时间
代码二
def run(n):
print("线程%s"%n)
time.sleep(2)
star_time = time.time()
for i in range(50):
run(i)
print('主线程')
print(float(time.time()-star_time))
运行的时间为100.27925944328308s
其实代码一通过运行的时候虽然最后的运行结果出来了,但编译器实际上还处于运行中,也就是代码一的主线程运行程序0.015604257583618164s而实际所有线程运行完毕的时间远远大于主线程,其实抽象可以理解成程序并行,只有一个线程从头执行到尾他就是主线程,因为线程都是并行,其他线程是运行自己的代码块,也就是上面代码实际的线程数等于50+1,代码一整体运行时间实际给加上sleep时间设置最长的线程,举个例子线程一1s,线程二 1.5s,一二并行所以最大时间就是1.5s
那如何可以测出线程整体的运行结果呢?
这里需要引入join(父),在字符串和os里面join是拼接,在thread模块中join是如果一个线程或者一个函数在执行过程中要调用另外一个线程,并且待到其完成以后才能接着执行,那么在调用这个线程时可以使用被调用线程的join方法,join()可设置等待秒数例如join(1)等待一秒
import threading
import time
#创建一个保存线程的列表
list_threading = []
def run(n,m):
print("线程%s"%n)
time.sleep(m)
star_time = time.time()
for i in range(50):
t1 = threading.Thread(target=run,args=(i,i/10+0.1) )
t1.start()
list_threading.append(t1)
#循环列表执行join
for ii in list_threading:
ii.join()
print('主线程'star_time-time.time())
运行结果是5.037472724914551s
我们发现最后的print等待了一会才打印,实际上就是主线程等待子线程~
因为所有线程是并发如果sleep设置时间相同,每个线程同时等待自己运行完毕执行下一个线程相当于所有线程都被同时卡主,同时释放,当sleep时间不同时一最长的线程被卡时间未结束
打印主线程和子线程~
import threading
def run(n):
print("线程%s"%n,threading.current_thread())
for i in range(50):
t1 = threading.Thread(target=run ,args=(i,))
t1.start()
#主线程
print(threading.current_thread())
线程守护setDaemon()函数的参数为True时开启,什么是线程守护,就是其他未被守护线程结束运算后,守护线程不管是否结束都挂掉~
例一·当未开启守护线程
import threading
import time
def run(n):
print("线程%s"%n)
time.sleep(2)
print("主线程死了所以不执行%s"%n)
for i in range(4):
t1= threading.Thread(target=run,args=(i,))
t1.start()
程序运行结果
线程0
线程1
线程2
线程3
主线程死了所以不执行3
主线程死了所以不执行1
主线程死了所以不执行0
主线程死了所以不执行2
上面的运行结果也可以明显看出线程的并发机制,线程同时并发一起到sleep(2)停止,然后又根据先后运行速度执行print
列二开启守护
import threading
import time
def run(n):
print("线程%s"%n)
time.sleep(2)
print("主线程死了所以不执行%s"%n)
for i in range(4):
t1= threading.Thread(target=run,args=(i,))
t1.setDaemon(True)
t1.start()
运行结果
线程0
线程1
线程2
线程3
通过运行结果发现因为是个主线程开启了守护,所以主线程结束其他线程也跟着结束~守护线程的生命周期在非守护线程结束时结束
五、线程锁
import threading
def run(n):
print("多线程%s"%n)
lock = threading.Lock()
for i in range(50):
#获得锁
lock.acquire()
t1 = threading.Thread(target=run, args=(i,))
t1.start()
#释放锁
lock.release()
信号量:
import threading
import time
def run(n):
# 获得锁
lock.acquire()
print("多线程%s"%n)
time.sleep(1)
# 释放锁
lock.release()
#信号量每执行完一个函数就会接着执行下一个,但五个一展式
lock = threading.BoundedSemaphore(5)
for i in range(50):
t1 = threading.Thread(target=run, args=(i,))
t1.start()
红路灯event 事件:
event = threading.Event()
event.clear()清除标记
event.set()建立标记
event.is_set()
event.wait()没有标记等待
import threading
import time
event = threading.Event()
def redlight():
count = 0
while True:
if count<5 and count>2.5:
event.clear()#把标志位清空
print("红灯")
elif count>5:
count =0
else:
print("绿灯")
event.set()
time.sleep(1)
count += 1
def car():
while True:
if event.is_set():
time.sleep(1)
print("111")
else:
print("wait....")
event.wait()