一、线程
1.1 什么是线程
操作系统 —— 工厂
进程 —— 车间
线程—— 流水线
cpu —— 电源
线程:cpu最小的执行单位
进程:资源集合/资源单位
线程运行 = 运行代码
进程运行 = 各种资源 + 线程
1.2 线程和进程的区别
线程 | 进程 |
---|---|
同一个进程下的线程资源共享 | 内存空间彼此隔离 |
快:只是告诉操作系统一个执行方案 | 慢:需要申请资源开辟空间 |
二、开启线程的两种方式
'''方式一'''
from threading import Thread
import time
def task():
print('子线程开始')
time.sleep(1)
print('子线程结束')
if __name__ == '__main__':
t = Thread(target=task) #初始化一个对象
t.start()
time.sleep(2)
print('主线程结束')
'''方式二'''
from threading import Thread
import time
class task(Thread):
print('子线程开始')
time.sleep(1)
print('子线程结束')
t = task()
t.start()
time.sleep(2)
print('主线程结束')
三、线程与进程的速度对比
from multiprocessing import Process
from threading import Thread
import time
def task(name):
print(f"{name}在运行")
time.sleep(3)
print(f"{name}结束")
if __name__ == '__main__':
p = Process(target=task,args=('子进程',))
t = Thread(target=task,args=('子线程',))
p.start()
t.start()
time.sleep(5)
print('主')
'''
子线程在运行
子进程在运行
子线程结束
子进程结束
主
### 充分证明了线程比进程快
'''
四、证明子线程共享资源
from threading import Thread
x = 100
def task():
global x
x = 1
if __name__ == '__main__':
t = Thread(target=task)
t.start()
print(x) #如果x被改为1,则证明子线程共享资源 #1
'''
综上所述,充分证明子线程共享资源
'''
五、线程的相关方法
5.1 join方法
等待子线程运行结束
'''join 方法'''
from threading import Thread
import time
def task(name,n):
print(f'{name}开始')
time.sleep(n)
print(f'{name}结束')
if __name__ == '__main__':
t1 = Thread(target=task,args=('子线程1',1))
t2 = Thread(target=task,args=('子线程2',2))
t3 = Thread(target=task,args=('子线程3',3))
l = [t1,t2,t3]
for t in l:
t.start()
t.join() #感知子线程的结束
print('主线程结束')
print(t.is_alive()) #查看t线程是否还活着,false 证明死了
5.2 其他方法
'''
Thread实例对象的方法
# isAlive(): 返回线程是否活动的。
# getName(): 返回线程名。
# setName(): 设置线程名。
threading模块提供的一些方法(这些模块需要提前导入):
# threading.currentThread(): 返回当前的线程变量。
# threading.enumerate(): 返回一个包含正在运行的线程的list。正在运行指线程启动后、结束前,不包括启动前和终止后的线程。
# threading.activeCount(): 返回正在运行的线程数量,与len(threading.enumerate())有相同的结果。
'''
from threading import Thread,current_thread,enumerate,active_count
import time
def task(name,n):
print(f'{name}开始')
time.sleep(n)
print(f'{name}结束')
if __name__ == '__main__':
t1 = Thread(target=task,args=('子线程1',1))
t2 = Thread(target=task,args=('子线程2',2))
l = [t1,t2]
for t in l:
t.start()
print(t1.is_alive()) # 查看t1线程是否还活着 #True证明还活着
print(t1.getName()) #获取t1线程名
t1.setName('大猪蹄子线程')
print(t1.getName()) #获取修改后的t1线程名
print(current_thread()) # 返回当前线程
print(enumerate()) #返回当前运行的线程的一个列表
print(active_count()) #返回当前正在运行的线程数量
t.join()
print('主线程结束')
'''
子线程1开始
子线程2开始
True
Thread-1
大猪蹄子线程
<_MainThread(MainThread, started 13384)>
[<_MainThread(MainThread, started 13384)>, <Thread(大猪蹄子线程, started 1736)>, <Thread(Thread-2, started 10788)>]
3
子线程1结束
子线程2结束
主线程结束
'''
六、守护线程
守护线程守护的是进程的运行周期
- 对主进程来说,运行完毕指的是主进程代码运行完毕
- 对主线程来说,运行完毕指的是主线程所在的进程内所有非守护线程统统运行完毕,主线程才算运行完毕
from threading import Thread
import time
def task1():
print('子线程1开始')
time.sleep(2)
print('子线程1结束')
print(t1.is_alive()) # True 当子线程1结束了,子线程1并没有死亡,也是在等待其他线程运行完毕
def task2():
print('子线程2开始')
time.sleep(3)
print('子线程2结束')
print(t1.is_alive()) # True 当子线程2结束了,子线程1就死了
if __name__ == '__main__':
t1 = Thread(target=task1) #初始化一个对象
t2 = Thread(target=task2) #初始化一个对象
t1.daemon = True #必须在start开始之前将它设置为守护进程
t1.start()
t2.start()
time.sleep(2)
print('主线程结束')
print(t1.is_alive()) #True 他没有因为主线程的结束而结束,而是等待子线程2运行完毕
'''
子线程1开始
子线程2开始
主线程结束
True
子线程1结束
True
子线程2结束
False
'''
七、多线程实现socket
'''服务器'''
import socket
from threading import Thread
sk_s = socket.socket() #实例化
sk_s.bind(('127.0.0.1',8008)) #绑定
sk_s.listen(5) #监听
def task(conn): #子线程
while True: #通信循环
msg = conn.recv(1024) #接收线程
conn.send(msg.upper()) #发送数据
if __name__ == '__main__':
while True: # 链接循环
print('等待客户端连接>>>>')
conn, addr = sk_s.accept() #等待接收
print(f'客户端{addr}连接成功')
t = Thread(target=task,args=(conn,)) #实例化一个线程t
t.start() #子线程开始
'''客户端'''
import socket
sk_c = socket.socket()
sk_c.connect(('127.0.0.1',8008))
while True:
msg = input('>>>').strip()
if msg == "q":
break
msg = msg.encode('utf8')
sk_c.send(msg)
data = sk_c.recv(1024)
print(data.decode('utf8'))
sk_c.close()