并发编程--多线程
线程就是一条流水线的工作过程的总称
线程是cpu的基本执行单位
特点:
- 每个进程都会有一个默认的线程
- 每个进程可以存在多个线程
- 同一进程中的所有线程之间数据是共享的
- 创建线程的开销远比创建进程小的多
主线程和子线程的区别:
- 线程之间没有父子之分,是平等的
- 主线程是由操作系统开启的,而子线程是由程序开启的
- 主线程代码执行完毕,也不会结束进程,而会等待所有行程执行完毕,才会结束
开启线程的两种方式
- 实例化Tread类,target参数用于指定子线程要执行的任务
from threading import Thread
def task():
print('子线程...')
t=Thread(target=task)
t.start()
print('over')
- 继承Tread类,覆盖run方法
from threading import Thread
class MyThread(Thread):
def run(self):
print('子线程')
t=MyThread()
t.start()
print('over')
线程与进程在使用方法上没有任何区别,不同的是开启子线程的代码可以写在任何位置
多进程是为了弥补多线程的缺憾而诞生的
线程和进程的区别
- 同一进程中,线程之间的数据共享
- 创建线程的开销远比创建进程小的多
- 无论开启了多少子线程PID都是不会变的
from threading import Thread
import os
def task():
print(os.getpid())
for i in range(100):
p=Thread(target=task)
p.start()
Thread类的常用属性
#threading模块包含的常用方法
import threading
print(threading.current_thread().name)#获取当前的线程对象
print(threading.active_count())#获取目前活跃的线程对象
print(threading.enumerate())#获取所有线程对象
t=Thread(name='aaa')
t.join()#主线程等待子线程结束
print(t.is_alive())#是否存活
print(t.name())#线程名称
print(t.isDaemon())#是否为守护线程
守护线程
设置守护线程的语法与进程相同,相同的是也必须放在线程开启前设置,否则抛出异常。
守护线程的特点:
守护线程会在被守护线程结束后立即结束
def task():
print('start...')
time.sleep(5)
print('end.....')
t=Thread(target=task)
t.daemon=True
t.start()
print('main over')
#输出结果 不会输出end....
from threading import Thread
import time
def task():
print("start....1")
time.sleep(3)
print("end......1")
def task2():
print("start....2")
time.sleep(4)
print("end......2")
t = Thread(target=task)
t.daemon = True
t.start()
t2 = Thread(target=task2)
t2.start()
print("main over!")
顺序:守护线程等待 主线程 等待 其余子线程
守护线程会随着所有非守护线程结束而结束。